remap 2.1.13 → 2.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/remap/compiler.rb +48 -40
- data/lib/remap/extensions/enumerable.rb +2 -0
- data/lib/remap/rule/block.rb +34 -0
- data/lib/remap/rule/map/enum.rb +88 -0
- data/lib/remap/rule/map/optional.rb +1 -1
- data/lib/remap/rule/map.rb +17 -9
- data/lib/remap/rule.rb +2 -0
- data/lib/remap/selector/index.rb +12 -3
- data/lib/remap/state/extension.rb +2 -2
- data/lib/remap/types.rb +1 -1
- data/lib/remap.rb +0 -1
- metadata +3 -9
- data/lib/remap/rule/each.rb +0 -38
- data/lib/remap/rule/embed.rb +0 -47
- data/lib/remap/rule/set.rb +0 -33
- data/lib/remap/rule/support/collection/empty.rb +0 -23
- data/lib/remap/rule/support/collection/filled.rb +0 -40
- data/lib/remap/rule/support/collection.rb +0 -19
- data/lib/remap/rule/support/enum.rb +0 -86
- data/lib/remap/rule/wrap.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88204af4f42ce85893ec029d953e2e6c417bbacba673522eedadca9561f8f749
|
4
|
+
data.tar.gz: 9e3e6040baf0426590b4c920d33f0979e74a084a19bbd87079d474a9e251663a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 612cf547b8207f305cf9b1f4788d3b36c0d487f0c42bdbf657336c04982060f6dd46a0cfc2a57c39588cef15287ede98205ab5beb46c9245b3270a99b586934d
|
7
|
+
data.tar.gz: a11492555b465f2d9f2db0611ed8d6457579dc6546805a9a867fc7b951061572f0faae84caec4be50907efa99e15647a8ae52aefd0de14362d29d6fea45cb166
|
data/lib/remap/compiler.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Remap
|
4
|
+
using State::Extension
|
5
|
+
|
4
6
|
# Constructs a {Rule} from the block passed to {Remap::Base.define}
|
5
7
|
class Compiler < Proxy
|
6
8
|
# @return [Array<Rule>]
|
@@ -29,12 +31,18 @@ module Remap
|
|
29
31
|
# @return [Rule]
|
30
32
|
def self.call(&block)
|
31
33
|
unless block
|
32
|
-
return Rule::
|
34
|
+
return Rule::VOID
|
33
35
|
end
|
34
36
|
|
35
|
-
new([]).tap do |compiler|
|
37
|
+
rules = new([]).tap do |compiler|
|
36
38
|
compiler.instance_exec(&block)
|
37
|
-
end.
|
39
|
+
end.rules
|
40
|
+
|
41
|
+
if rules.empty?
|
42
|
+
return Rule::VOID
|
43
|
+
end
|
44
|
+
|
45
|
+
Rule::Block.new(rules)
|
38
46
|
end
|
39
47
|
|
40
48
|
# Maps input path [input] to output path [to]
|
@@ -59,13 +67,7 @@ module Remap
|
|
59
67
|
#
|
60
68
|
# @return [Rule::Map::Required]
|
61
69
|
def map(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
|
62
|
-
add
|
63
|
-
path: {
|
64
|
-
output: [to].flatten,
|
65
|
-
input: path.flatten
|
66
|
-
},
|
67
|
-
backtrace: backtrace,
|
68
|
-
rule: call(&block))
|
70
|
+
add rule(*path, to: to, backtrace: backtrace, &block)
|
69
71
|
end
|
70
72
|
|
71
73
|
# Optional version of {#map}
|
@@ -92,13 +94,7 @@ module Remap
|
|
92
94
|
#
|
93
95
|
# @return [Rule::Map::Optional]
|
94
96
|
def map?(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
|
95
|
-
add
|
96
|
-
path: {
|
97
|
-
output: [to].flatten,
|
98
|
-
input: path.flatten
|
99
|
-
},
|
100
|
-
backtrace: backtrace,
|
101
|
-
rule: call(&block))
|
97
|
+
add rule?(*path, to: to, backtrace: backtrace, &block)
|
102
98
|
end
|
103
99
|
|
104
100
|
# Select a path and uses the same path as output
|
@@ -122,7 +118,7 @@ module Remap
|
|
122
118
|
#
|
123
119
|
# @return [Rule::Map::Required]
|
124
120
|
def get(*path, backtrace: Kernel.caller, &block)
|
125
|
-
|
121
|
+
add rule(path, to: path, backtrace: backtrace, &block)
|
126
122
|
end
|
127
123
|
|
128
124
|
# Optional version of {#get}
|
@@ -147,7 +143,7 @@ module Remap
|
|
147
143
|
#
|
148
144
|
# @return [Rule::Map::Optional]
|
149
145
|
def get?(*path, backtrace: Kernel.caller, &block)
|
150
|
-
|
146
|
+
add rule?(path, to: path, backtrace: backtrace, &block)
|
151
147
|
end
|
152
148
|
|
153
149
|
# Maps using mapper
|
@@ -189,9 +185,13 @@ module Remap
|
|
189
185
|
raise ArgumentError, "#embed does not take a block"
|
190
186
|
end
|
191
187
|
|
192
|
-
|
193
|
-
|
194
|
-
|
188
|
+
embeding = rule(&block).add do |state, &error|
|
189
|
+
mapper.call!(state.set(mapper: mapper)) do |failure|
|
190
|
+
next error[failure]
|
191
|
+
end.except(:mapper, :scope)
|
192
|
+
end
|
193
|
+
|
194
|
+
add embeding
|
195
195
|
end
|
196
196
|
|
197
197
|
# Set a static value
|
@@ -234,9 +234,7 @@ module Remap
|
|
234
234
|
raise ArgumentError, "#set does not take a block"
|
235
235
|
end
|
236
236
|
|
237
|
-
add
|
238
|
-
rescue Dry::Struct::Error => e
|
239
|
-
raise ArgumentError, e.message
|
237
|
+
add rule(to: path).add { to.call(_1) }
|
240
238
|
end
|
241
239
|
|
242
240
|
# Maps to path from map with block in between
|
@@ -261,7 +259,7 @@ module Remap
|
|
261
259
|
#
|
262
260
|
# @return [Rule::Map]
|
263
261
|
def to(*path, map: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
|
264
|
-
|
262
|
+
add rule(*map, to: path, backtrace: backtrace, &block)
|
265
263
|
end
|
266
264
|
|
267
265
|
# Optional version of {#to}
|
@@ -287,7 +285,7 @@ module Remap
|
|
287
285
|
#
|
288
286
|
# @return [Rule::Map::Optional]
|
289
287
|
def to?(*path, map: EMPTY_ARRAY, &block)
|
290
|
-
|
288
|
+
add rule?(*map, to: path, &block)
|
291
289
|
end
|
292
290
|
|
293
291
|
# Iterates over the input value, passes each value
|
@@ -319,7 +317,7 @@ module Remap
|
|
319
317
|
raise ArgumentError, "#each requires a block"
|
320
318
|
end
|
321
319
|
|
322
|
-
add
|
320
|
+
add rule(all, &block)
|
323
321
|
end
|
324
322
|
|
325
323
|
# Wraps output in type
|
@@ -352,9 +350,7 @@ module Remap
|
|
352
350
|
raise ArgumentError, "#wrap requires a block"
|
353
351
|
end
|
354
352
|
|
355
|
-
add
|
356
|
-
rescue Dry::Struct::Error => e
|
357
|
-
raise ArgumentError, e.message
|
353
|
+
add rule(&block).then { Array.wrap(_1) }
|
358
354
|
end
|
359
355
|
|
360
356
|
# Selects all elements
|
@@ -521,19 +517,31 @@ module Remap
|
|
521
517
|
at(-1)
|
522
518
|
end
|
523
519
|
|
524
|
-
# The final rule
|
525
|
-
#
|
526
|
-
# @return [Rule]
|
527
|
-
#
|
528
|
-
# @private
|
529
|
-
def rule
|
530
|
-
Rule::Collection.call(rules: rules)
|
531
|
-
end
|
532
|
-
|
533
520
|
private
|
534
521
|
|
535
522
|
def add(rule)
|
536
523
|
rule.tap { rules << rule }
|
537
524
|
end
|
525
|
+
|
526
|
+
def rule(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
|
527
|
+
Rule::Map::Required.call({
|
528
|
+
path: {
|
529
|
+
output: [to].flatten,
|
530
|
+
input: path.flatten
|
531
|
+
},
|
532
|
+
backtrace: backtrace,
|
533
|
+
rule: call(&block)
|
534
|
+
})
|
535
|
+
end
|
536
|
+
|
537
|
+
def rule?(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
|
538
|
+
Rule::Map::Optional.call({
|
539
|
+
path: {
|
540
|
+
output: [to].flatten,
|
541
|
+
input: path.flatten
|
542
|
+
},
|
543
|
+
rule: call(&block)
|
544
|
+
})
|
545
|
+
end
|
538
546
|
end
|
539
547
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
class Rule
|
5
|
+
using State::Extension
|
6
|
+
|
7
|
+
class Block < Unit
|
8
|
+
# @return [Array<Rule>]
|
9
|
+
attribute :rules, [Types::Rule]
|
10
|
+
|
11
|
+
# Represents a non-empty define block with one or more rules
|
12
|
+
# Calls every {#rules} with state and merges the output
|
13
|
+
#
|
14
|
+
# @param state [State]
|
15
|
+
#
|
16
|
+
# @return [State]
|
17
|
+
def call(state, &error)
|
18
|
+
unless block_given?
|
19
|
+
raise ArgumentError, "Block#call(state, &error) requires a block"
|
20
|
+
end
|
21
|
+
|
22
|
+
if rules.empty?
|
23
|
+
return state.except(:value)
|
24
|
+
end
|
25
|
+
|
26
|
+
rules.map do |rule|
|
27
|
+
rule.call(state) do |failure|
|
28
|
+
return error[failure]
|
29
|
+
end
|
30
|
+
end.reduce(&:combine)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Remap
|
4
|
+
class Rule
|
5
|
+
class Map
|
6
|
+
class Enum < Proxy
|
7
|
+
include Dry::Monads[:maybe]
|
8
|
+
|
9
|
+
# @return [Hash]
|
10
|
+
option :mappings, default: -> { Hash.new { default } }
|
11
|
+
|
12
|
+
# @return [Maybe]
|
13
|
+
option :default, default: -> { None() }
|
14
|
+
|
15
|
+
alias execute instance_eval
|
16
|
+
|
17
|
+
# Builds an enumeration using the block as context
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# enum = Remap::Rule::Map::Enum.call do
|
21
|
+
# from "B", to: "C"
|
22
|
+
# value "A"
|
23
|
+
# otherwise "D"
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# enum.get("A") # => "A"
|
27
|
+
# enum.get("B") # => "C"
|
28
|
+
# enum.get("C") # => "C"
|
29
|
+
# enum.get("MISSING") # => "D"
|
30
|
+
#
|
31
|
+
# @return [Any]
|
32
|
+
def self.call(&block)
|
33
|
+
unless block
|
34
|
+
raise ArgumentError, "no block given"
|
35
|
+
end
|
36
|
+
|
37
|
+
new.tap { _1.execute(&block) }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Translates key into a value using predefined mappings
|
41
|
+
#
|
42
|
+
# @param key [#hash]
|
43
|
+
#
|
44
|
+
# @yield [String]
|
45
|
+
# If the key is not found & no default value is set
|
46
|
+
#
|
47
|
+
# @return [Any]
|
48
|
+
def get(key, &error)
|
49
|
+
unless error
|
50
|
+
return get(key) { raise Error, _1 }
|
51
|
+
end
|
52
|
+
|
53
|
+
self[key].bind { return _1 }.or do
|
54
|
+
error["Enum key [#{key}] not found among [#{mappings.keys.inspect}]"]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
alias call get
|
58
|
+
|
59
|
+
# @return [Maybe]
|
60
|
+
def [](key)
|
61
|
+
mappings[key]
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [void]
|
65
|
+
def from(*keys, to:)
|
66
|
+
value = Some(to)
|
67
|
+
|
68
|
+
keys.each do |key|
|
69
|
+
mappings[key] = value
|
70
|
+
mappings[to] = value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @return [void]
|
75
|
+
def value(*ids)
|
76
|
+
ids.each do |id|
|
77
|
+
from(id, to: id)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [void]
|
82
|
+
def otherwise(value)
|
83
|
+
mappings.default = Some(value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/remap/rule/map.rb
CHANGED
@@ -43,15 +43,19 @@ module Remap
|
|
43
43
|
#
|
44
44
|
# @abstract
|
45
45
|
def call(state, &error)
|
46
|
-
unless
|
46
|
+
unless block_given?
|
47
47
|
raise ArgumentError, "Map#call(state, &error) requires error handler block"
|
48
48
|
end
|
49
49
|
|
50
50
|
notice = catch :fatal do
|
51
51
|
return path.input.call(state) do |inner_state|
|
52
|
-
rule.call(inner_state) do |failure|
|
52
|
+
other_state = rule.call(inner_state) do |failure|
|
53
53
|
return error[failure]
|
54
|
-
end
|
54
|
+
end
|
55
|
+
|
56
|
+
callback(other_state) do |failure|
|
57
|
+
return error[failure]
|
58
|
+
end
|
55
59
|
end.then(&path.output)
|
56
60
|
end
|
57
61
|
|
@@ -181,23 +185,27 @@ module Remap
|
|
181
185
|
end
|
182
186
|
end
|
183
187
|
|
184
|
-
private
|
185
|
-
|
186
188
|
# @return [self]
|
187
189
|
def add(&block)
|
188
190
|
tap { fn << block }
|
189
191
|
end
|
190
192
|
|
193
|
+
private
|
194
|
+
|
191
195
|
# @return [Array<Proc>]
|
192
196
|
def fn
|
193
197
|
@fn ||= []
|
194
198
|
end
|
195
199
|
|
196
200
|
# @return [Proc]
|
197
|
-
def callback
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
+
def callback(state, &error)
|
202
|
+
unless block_given?
|
203
|
+
raise ArgumentError, "Map#callback(state, &error) requires error handler block"
|
204
|
+
end
|
205
|
+
|
206
|
+
fn.reduce(state) do |inner, fn|
|
207
|
+
fn[inner] do |failure|
|
208
|
+
return error[failure]
|
201
209
|
end
|
202
210
|
end
|
203
211
|
end
|
data/lib/remap/rule.rb
CHANGED
data/lib/remap/selector/index.rb
CHANGED
@@ -8,8 +8,15 @@ module Remap
|
|
8
8
|
#
|
9
9
|
# @example Select the value at index 1 from a array
|
10
10
|
# state = Remap::State.call([:one, :two, :tree])
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# index = Remap::Selector::Index.new(1)
|
12
|
+
#
|
13
|
+
# result = index.call(state) do |element|
|
14
|
+
# element.fmap do |value|
|
15
|
+
# value.upcase
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
|
19
|
+
# result.fetch(:value) # => :TWO
|
13
20
|
class Index < Unit
|
14
21
|
# @return [Integer]
|
15
22
|
attribute :index, Integer
|
@@ -25,7 +32,9 @@ module Remap
|
|
25
32
|
#
|
26
33
|
# @return [State<U>]
|
27
34
|
def call(outer_state, &block)
|
28
|
-
|
35
|
+
unless block_given?
|
36
|
+
raise ArgumentError, "The index selector requires an iteration block"
|
37
|
+
end
|
29
38
|
|
30
39
|
outer_state.bind(index: index) do |array, state|
|
31
40
|
requirement[array] do
|
@@ -351,7 +351,7 @@ module Remap
|
|
351
351
|
#
|
352
352
|
# @return [Struct]
|
353
353
|
def context(value, context: self, &error)
|
354
|
-
::Struct.new(*keys, *options.keys, keyword_init: true) do
|
354
|
+
::Struct.new(*keys, *options.keys, :state, keyword_init: true) do
|
355
355
|
define_method :method_missing do |name, *|
|
356
356
|
error["Method [#{name}] not defined"]
|
357
357
|
end
|
@@ -359,7 +359,7 @@ module Remap
|
|
359
359
|
define_method :skip! do |message = "Manual skip!"|
|
360
360
|
context.ignore!(message)
|
361
361
|
end
|
362
|
-
end.new(**to_hash, **options, value: value)
|
362
|
+
end.new(**to_hash, **options, value: value, state: self)
|
363
363
|
end
|
364
364
|
end
|
365
365
|
end
|
data/lib/remap/types.rb
CHANGED
@@ -15,7 +15,7 @@ module Remap
|
|
15
15
|
Enumerable = Any.constrained(type: Enumerable)
|
16
16
|
Nothing = Constant(Remap::Nothing)
|
17
17
|
Mapper = Interface(:call!)
|
18
|
-
Rule = Interface(:call)
|
18
|
+
Rule = Interface(:call) | Instance(Proc)
|
19
19
|
Key = Interface(:hash)
|
20
20
|
|
21
21
|
# Validates a state according to State::Schema
|
data/lib/remap.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: remap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Linus Oleander
|
@@ -279,18 +279,12 @@ files:
|
|
279
279
|
- lib/remap/path_error.rb
|
280
280
|
- lib/remap/proxy.rb
|
281
281
|
- lib/remap/rule.rb
|
282
|
-
- lib/remap/rule/
|
283
|
-
- lib/remap/rule/embed.rb
|
282
|
+
- lib/remap/rule/block.rb
|
284
283
|
- lib/remap/rule/map.rb
|
284
|
+
- lib/remap/rule/map/enum.rb
|
285
285
|
- lib/remap/rule/map/optional.rb
|
286
286
|
- lib/remap/rule/map/required.rb
|
287
|
-
- lib/remap/rule/set.rb
|
288
|
-
- lib/remap/rule/support/collection.rb
|
289
|
-
- lib/remap/rule/support/collection/empty.rb
|
290
|
-
- lib/remap/rule/support/collection/filled.rb
|
291
|
-
- lib/remap/rule/support/enum.rb
|
292
287
|
- lib/remap/rule/void.rb
|
293
|
-
- lib/remap/rule/wrap.rb
|
294
288
|
- lib/remap/selector.rb
|
295
289
|
- lib/remap/selector/all.rb
|
296
290
|
- lib/remap/selector/index.rb
|
data/lib/remap/rule/each.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
using State::Extension
|
6
|
-
|
7
|
-
# Iterates over a rule, even if the rule is not a collection
|
8
|
-
#
|
9
|
-
# @example Upcase each value in an array
|
10
|
-
# state = Remap::State.call(["John", "Jane"])
|
11
|
-
# upcase = Remap::Rule::Map.call({}).then(&:upcase)
|
12
|
-
# each = Remap::Rule::Each.call(rule: upcase)
|
13
|
-
# error = -> failure { raise failure.exception }
|
14
|
-
# each.call(state, &error).fetch(:value) # => ["JOHN", "JANE"]
|
15
|
-
class Each < Unit
|
16
|
-
# @return [Rule]
|
17
|
-
attribute :rule, Types::Rule
|
18
|
-
|
19
|
-
# Iterates over state and passes each value to rule
|
20
|
-
# Restores element, key & index before returning state
|
21
|
-
#
|
22
|
-
# @param state [State<Enumerable>]
|
23
|
-
#
|
24
|
-
# @return [State<Enumerable>]
|
25
|
-
def call(state, &error)
|
26
|
-
unless error
|
27
|
-
raise ArgumentError, "Each#call(state, &error) requires a block"
|
28
|
-
end
|
29
|
-
|
30
|
-
state.map do |inner_state|
|
31
|
-
rule.call(inner_state) do |failure|
|
32
|
-
return error[failure]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/remap/rule/embed.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
using State::Extension
|
6
|
-
|
7
|
-
# Embed mappers into each other
|
8
|
-
#
|
9
|
-
# @example Embed Mapper A into B
|
10
|
-
# class Car < Remap::Base
|
11
|
-
# define do
|
12
|
-
# map :name, to: :model
|
13
|
-
# end
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# class Person < Remap::Base
|
17
|
-
# define do
|
18
|
-
# to :person do
|
19
|
-
# to :car do
|
20
|
-
# embed Car
|
21
|
-
# end
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# Person.call({name: "Volvo"}) # => { person: { car: { model: "Volvo" } } }
|
27
|
-
class Embed < Unit
|
28
|
-
# @return [#call!]
|
29
|
-
attribute :mapper, Types::Mapper
|
30
|
-
|
31
|
-
# Evaluates input against mapper and returns the result
|
32
|
-
#
|
33
|
-
# @param state [State<T>]
|
34
|
-
#
|
35
|
-
# @return [State<U>]
|
36
|
-
def call(state, &error)
|
37
|
-
unless error
|
38
|
-
raise ArgumentError, "A block is required to evaluate the embed"
|
39
|
-
end
|
40
|
-
|
41
|
-
mapper.call!(state.set(mapper: mapper)) do |failure|
|
42
|
-
return error[failure]
|
43
|
-
end.except(:mapper, :scope)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/remap/rule/set.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
using State::Extension
|
6
|
-
|
7
|
-
# Set path to a static value
|
8
|
-
#
|
9
|
-
# @example Set path [:a, :b] to value "C"
|
10
|
-
# value = Remap::Static::Fixed.new(value: "a value")
|
11
|
-
# set = Remap::Rule::Set.new(value: value, path: [:a, :b])
|
12
|
-
# state = Remap::State.call("ANY VALUE")
|
13
|
-
# set.call(state).fetch(:value) # => { a: { b: "a value" } }
|
14
|
-
#
|
15
|
-
# @example Set path [:a, :b] to option :c
|
16
|
-
# value = Remap::Static::Option.new(name: :c)
|
17
|
-
# set = Remap::Rule::Set.new(value: value, path: [:a, :b])
|
18
|
-
# state = Remap::State.call("ANY VALUE", options: { c: "C" })
|
19
|
-
# set.call(state).fetch(:value) # => { a: { b: "C" } }
|
20
|
-
class Set < Concrete
|
21
|
-
# @return [Static]
|
22
|
-
attribute :value, Static, alias: :rule
|
23
|
-
|
24
|
-
# @return [Path::Output]
|
25
|
-
attribute :path, Path::Output
|
26
|
-
|
27
|
-
# @see Rule#call
|
28
|
-
def call(...)
|
29
|
-
rule.call(...).then(&path)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
class Collection
|
6
|
-
using State::Extension
|
7
|
-
|
8
|
-
# Represents an empty rule block
|
9
|
-
class Empty < Unit
|
10
|
-
attribute? :rules, Value(EMPTY_ARRAY), default: EMPTY_ARRAY
|
11
|
-
|
12
|
-
# Represents an empty define block, without any rules
|
13
|
-
#
|
14
|
-
# @param state [State<T>]
|
15
|
-
#
|
16
|
-
# @return [State<T>]
|
17
|
-
def call(state)
|
18
|
-
state.notice!("No rules, empty block")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
class Collection
|
6
|
-
using State::Extension
|
7
|
-
|
8
|
-
# Represents a non-empty rule block
|
9
|
-
#
|
10
|
-
# @example A collection containing a single rule
|
11
|
-
# state = Remap::State.call("A")
|
12
|
-
# void = Remap::Rule::Void.call({})
|
13
|
-
# rule = Remap::Rule::Collection.call([void])
|
14
|
-
# error = -> failure { raise failure.exception }
|
15
|
-
# rule.call(state, &error).fetch(:value) # => "A"
|
16
|
-
class Filled < Unit
|
17
|
-
# @return [Array<Rule>]
|
18
|
-
attribute :rules, [Types.Interface(:call)], min_size: 1
|
19
|
-
|
20
|
-
# Represents a non-empty define block with one or more rules
|
21
|
-
# Calls every {#rules} with state and merges the output
|
22
|
-
#
|
23
|
-
# @param state [State]
|
24
|
-
#
|
25
|
-
# @return [State]
|
26
|
-
def call(state, &error)
|
27
|
-
unless error
|
28
|
-
raise ArgumentError, "Collection::Filled#call(state, &error) requires a block"
|
29
|
-
end
|
30
|
-
|
31
|
-
rules.map do |rule|
|
32
|
-
rule.call(state) do |failure|
|
33
|
-
return error[failure]
|
34
|
-
end
|
35
|
-
end.reduce(&:combine)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
# Represents a block defined by a rule
|
6
|
-
class Collection < Abstract
|
7
|
-
attribute :rules, Array
|
8
|
-
|
9
|
-
# @param state [State]
|
10
|
-
#
|
11
|
-
# @return [State]
|
12
|
-
#
|
13
|
-
# @abstract
|
14
|
-
def call(state)
|
15
|
-
raise NotImplementedError, "#{self.class}#call not implemented"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
class Enum < Proxy
|
6
|
-
include Dry::Monads[:maybe]
|
7
|
-
|
8
|
-
# @return [Hash]
|
9
|
-
option :mappings, default: -> { Hash.new { default } }
|
10
|
-
|
11
|
-
# @return [Maybe]
|
12
|
-
option :default, default: -> { None() }
|
13
|
-
|
14
|
-
alias execute instance_eval
|
15
|
-
|
16
|
-
# Builds an enumeration using the block as context
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# enum = Remap::Rule::Enum.call do
|
20
|
-
# from "B", to: "C"
|
21
|
-
# value "A"
|
22
|
-
# otherwise "D"
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# enum.get("A") # => "A"
|
26
|
-
# enum.get("B") # => "C"
|
27
|
-
# enum.get("C") # => "C"
|
28
|
-
# enum.get("MISSING") # => "D"
|
29
|
-
#
|
30
|
-
# @return [Any]
|
31
|
-
def self.call(&block)
|
32
|
-
unless block
|
33
|
-
raise ArgumentError, "no block given"
|
34
|
-
end
|
35
|
-
|
36
|
-
new.tap { _1.execute(&block) }
|
37
|
-
end
|
38
|
-
|
39
|
-
# Translates key into a value using predefined mappings
|
40
|
-
#
|
41
|
-
# @param key [#hash]
|
42
|
-
#
|
43
|
-
# @yield [String]
|
44
|
-
# If the key is not found & no default value is set
|
45
|
-
#
|
46
|
-
# @return [Any]
|
47
|
-
def get(key, &error)
|
48
|
-
unless error
|
49
|
-
return get(key) { raise Error, _1 }
|
50
|
-
end
|
51
|
-
|
52
|
-
self[key].bind { return _1 }.or do
|
53
|
-
error["Enum key [#{key}] not found among [#{mappings.keys.inspect}]"]
|
54
|
-
end
|
55
|
-
end
|
56
|
-
alias call get
|
57
|
-
|
58
|
-
# @return [Maybe]
|
59
|
-
def [](key)
|
60
|
-
mappings[key]
|
61
|
-
end
|
62
|
-
|
63
|
-
# @return [void]
|
64
|
-
def from(*keys, to:)
|
65
|
-
value = Some(to)
|
66
|
-
|
67
|
-
keys.each do |key|
|
68
|
-
mappings[key] = value
|
69
|
-
mappings[to] = value
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# @return [void]
|
74
|
-
def value(*ids)
|
75
|
-
ids.each do |id|
|
76
|
-
from(id, to: id)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# @return [void]
|
81
|
-
def otherwise(value)
|
82
|
-
mappings.default = Some(value)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/lib/remap/rule/wrap.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Remap
|
4
|
-
class Rule
|
5
|
-
using State::Extension
|
6
|
-
|
7
|
-
# Wraps rule in a type
|
8
|
-
#
|
9
|
-
# @example Maps { name: "Ford" } to { cars: ["Ford"] }
|
10
|
-
# class Mapper < Remap::Base
|
11
|
-
# define do
|
12
|
-
# to :cars do
|
13
|
-
# wrap(:array) do
|
14
|
-
# map :name
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# Mapper.call({ name: "Ford" }) # => { cars: ["Ford"] }
|
21
|
-
class Wrap < Concrete
|
22
|
-
# @return [:array]
|
23
|
-
attribute :type, Value(:array)
|
24
|
-
|
25
|
-
# @return [Rule]
|
26
|
-
attribute :rule, Types::Rule
|
27
|
-
|
28
|
-
# Wraps the output from {#rule} in a {#type}
|
29
|
-
#
|
30
|
-
# @see Rule#call
|
31
|
-
def call(...)
|
32
|
-
rule.call(...).fmap do |value|
|
33
|
-
Array.wrap(value)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|