remap 2.0.3 → 2.1.0

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/remap/base.rb +229 -75
  3. data/lib/remap/compiler.rb +127 -37
  4. data/lib/remap/constructor/argument.rb +20 -6
  5. data/lib/remap/constructor/keyword.rb +20 -4
  6. data/lib/remap/constructor/none.rb +3 -4
  7. data/lib/remap/constructor.rb +12 -5
  8. data/lib/remap/contract.rb +27 -0
  9. data/lib/remap/extensions/enumerable.rb +48 -0
  10. data/lib/remap/extensions/hash.rb +13 -0
  11. data/lib/remap/extensions/object.rb +37 -0
  12. data/lib/remap/failure.rb +25 -15
  13. data/lib/remap/iteration/array.rb +20 -11
  14. data/lib/remap/iteration/hash.rb +21 -13
  15. data/lib/remap/iteration/other.rb +7 -7
  16. data/lib/remap/iteration.rb +8 -2
  17. data/lib/remap/mapper/and.rb +29 -7
  18. data/lib/remap/mapper/binary.rb +3 -6
  19. data/lib/remap/mapper/or.rb +29 -6
  20. data/lib/remap/mapper/support/operations.rb +40 -0
  21. data/lib/remap/mapper/xor.rb +29 -7
  22. data/lib/remap/mapper.rb +1 -48
  23. data/lib/remap/notice/traced.rb +19 -0
  24. data/lib/remap/notice/untraced.rb +11 -0
  25. data/lib/remap/notice.rb +34 -0
  26. data/lib/remap/operation.rb +26 -13
  27. data/lib/remap/path/input.rb +37 -0
  28. data/lib/remap/path/output.rb +26 -0
  29. data/lib/remap/path.rb +22 -0
  30. data/lib/remap/path_error.rb +13 -0
  31. data/lib/remap/proxy.rb +18 -0
  32. data/lib/remap/rule/each.rb +25 -24
  33. data/lib/remap/rule/embed.rb +33 -28
  34. data/lib/remap/rule/map/optional.rb +42 -0
  35. data/lib/remap/rule/map/required.rb +35 -0
  36. data/lib/remap/rule/map.rb +176 -55
  37. data/lib/remap/rule/set.rb +23 -33
  38. data/lib/remap/rule/support/collection/empty.rb +7 -7
  39. data/lib/remap/rule/support/collection/filled.rb +21 -8
  40. data/lib/remap/rule/support/collection.rb +11 -3
  41. data/lib/remap/rule/support/enum.rb +44 -21
  42. data/lib/remap/rule/void.rb +17 -18
  43. data/lib/remap/rule/wrap.rb +25 -17
  44. data/lib/remap/rule.rb +8 -1
  45. data/lib/remap/selector/all.rb +29 -7
  46. data/lib/remap/selector/index.rb +24 -16
  47. data/lib/remap/selector/key.rb +31 -16
  48. data/lib/remap/selector.rb +17 -0
  49. data/lib/remap/state/extension.rb +182 -208
  50. data/lib/remap/state/schema.rb +1 -1
  51. data/lib/remap/state.rb +30 -4
  52. data/lib/remap/static/fixed.rb +14 -3
  53. data/lib/remap/static/option.rb +21 -6
  54. data/lib/remap/static.rb +13 -0
  55. data/lib/remap/struct.rb +1 -0
  56. data/lib/remap/types.rb +13 -28
  57. data/lib/remap.rb +15 -19
  58. metadata +91 -89
  59. data/lib/remap/result.rb +0 -11
  60. data/lib/remap/rule/support/path.rb +0 -45
  61. data/lib/remap/state/types.rb +0 -11
  62. data/lib/remap/success.rb +0 -29
  63. data/lib/remap/version.rb +0 -5
@@ -2,18 +2,40 @@
2
2
 
3
3
  module Remap
4
4
  class Selector
5
- class All < Concrete
6
- using State::Extension
5
+ using State::Extension
7
6
 
7
+ # Selects all elements from a state
8
+ #
9
+ # @example Select all keys from array hash
10
+ # state = Remap::State.call([{a: "A1"}, {a: "A2"}])
11
+ # all = Remap::Selector::All.new
12
+ # result = all.call(state) do |other_state|
13
+ # value = other_state.fetch(:value).class
14
+ # other_state.merge(value: value)
15
+ # end
16
+ # result.fetch(:value) # => [Hash, Hash]
17
+ class All < Concrete
8
18
  requirement Types::Enumerable
9
19
 
10
- def call(state, &block)
11
- state.bind(quantifier: "*") do |enumerable, inner_state, &error|
12
- requirement[enumerable] do
13
- return error["Expected an enumeration"]
20
+ # Iterates over state and passes each value to block
21
+ #
22
+ # @param outer_state [State<Enumerable<T>>]
23
+ #
24
+ # @yieldparam [State<T>]
25
+ # @yieldreturn [State<U>]
26
+ #
27
+ # @return [State<U>]
28
+ def call(outer_state, &block)
29
+ unless block_given?
30
+ raise ArgumentError, "All selector requires an iteration block"
31
+ end
32
+
33
+ outer_state.bind(quantifier: "*") do |enum, state|
34
+ requirement[enum] do
35
+ state.fatal!("Expected enumeration but got %p (%s)", enum, enum.class)
14
36
  end
15
37
 
16
- inner_state.map(&block)
38
+ state.map(&block)
17
39
  end
18
40
  end
19
41
  end
@@ -2,36 +2,44 @@
2
2
 
3
3
  module Remap
4
4
  class Selector
5
+ using State::Extension
6
+
7
+ # Selects value at given index
8
+ #
9
+ # @example Select the value at index 1 from a array
10
+ # state = Remap::State.call([:one, :two, :tree])
11
+ # result = Remap::Selector::Index.new(1).call(state)
12
+ # result.fetch(:value) # => :two
5
13
  class Index < Unit
6
- using State::Extension
7
-
14
+ # @return [Integer]
8
15
  attribute :index, Integer
9
16
 
10
17
  requirement Types::Array
11
18
 
12
- # Fetches {#input[value]} and passes it to {block}
19
+ # Selects the {#index}th element from state and passes it to block
13
20
  #
14
- # @param [State] state
21
+ # @param outer_state [State<Array<T>>]
15
22
  #
16
- # @yieldparam [State]
17
- # @yieldreturn [State<T>]
18
-
19
- # @return [State<T>]
20
- def call(state, &block)
21
- unless block
22
- raise ArgumentError, "no block given"
23
- end
23
+ # @yieldparam [State<T>]
24
+ # @yieldreturn [State<U>]
25
+ #
26
+ # @return [State<U>]
27
+ def call(outer_state, &block)
28
+ return call(outer_state, &:itself) unless block
24
29
 
25
- state.bind(index: index) do |array, inner_state, &error|
30
+ outer_state.bind(index: index) do |array, state|
26
31
  requirement[array] do
27
- return error["Expected an array"]
32
+ state.fatal!("Expected array but got %p (%s)", array, array.class)
28
33
  end
29
34
 
30
35
  element = array.fetch(index) do
31
- return error["No element on index at index #{index}"]
36
+ state.ignore!("Index %s in array %p (%s) not found",
37
+ index,
38
+ array,
39
+ array.class)
32
40
  end
33
41
 
34
- block[inner_state.set(element, index: index)]
42
+ state.set(element, index: index).then(&block)
35
43
  end
36
44
  end
37
45
  end
@@ -2,35 +2,50 @@
2
2
 
3
3
  module Remap
4
4
  class Selector
5
+ using State::Extension
6
+
7
+ # Selects value at key from state
8
+ #
9
+ # @example Select the value at key :name from a hash
10
+ # state = Remap::State.call({ name: "John" })
11
+ # selector = Remap::Selector::Key.new(:name)
12
+ #
13
+ # selector.call(state) do |state|
14
+ # state.fetch(:value)
15
+ # end
5
16
  class Key < Unit
6
- using State::Extension
17
+ # @return [#hash
18
+ attribute :key, Types::Key
7
19
 
8
- attribute :key, Types::Hash.not
9
- requirement Types::Hash.constrained(min_size: 1)
20
+ requirement Types::Hash
10
21
 
11
- # Fetches {#input[value]} and passes it to {block}
22
+ # Selects {#key} from state and passes it to block
12
23
  #
13
- # @param [State] state
24
+ # @param outer_state [State<Hash<K, V>>]
14
25
  #
15
- # @yieldparam [State]
16
- # @yieldreturn [State<T>]
17
-
18
- # @return [State<T>]
19
- def call(state, &block)
20
- unless block
21
- return call(state, &:itself)
26
+ # @yieldparam [State<V>]
27
+ # @yieldreturn [State<U>]
28
+ #
29
+ # @return [State<U>]
30
+ def call(outer_state, &block)
31
+ unless block_given?
32
+ raise ArgumentError, "The key selector requires an iteration block"
22
33
  end
23
34
 
24
- state.bind(key: key) do |hash, inner_state, &error|
35
+ outer_state.bind(key: key) do |hash, state|
25
36
  requirement[hash] do
26
- return error["Expected a hash"]
37
+ state.fatal!("Expected hash but got %p (%s)", hash, hash.class)
27
38
  end
28
39
 
29
40
  value = hash.fetch(key) do
30
- return error["Key [#{key}] not found"]
41
+ state.ignore!("Key %p (%s) not found in hash %p (%s)",
42
+ key,
43
+ key.class,
44
+ hash,
45
+ hash.class)
31
46
  end
32
47
 
33
- block[inner_state.set(value, key: key)]
48
+ state.set(value, key: key).then(&block)
34
49
  end
35
50
  end
36
51
  end
@@ -1,12 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Remap
4
+ # Defines how a path element, or selector
5
+ # Specifies how a value is extracted from a state
4
6
  class Selector < Dry::Interface
5
7
  defines :requirement, type: Types::Any.constrained(type: Dry::Types::Type)
6
8
  requirement Types::Any
7
9
 
10
+ # Selects value from state, package it as a state and passes it to block
11
+ #
12
+ # @param state [State]
13
+ #
14
+ # @yieldparam [State]
15
+ # @yieldreturn [State]
16
+ #
17
+ # @return [State]
18
+ #
19
+ # @abstract
20
+ def call(state)
21
+ raise NotImplementedError, "#{self.class}#call not implemented"
22
+ end
23
+
8
24
  private
9
25
 
26
+ # @return [Dry::Types::Type]
10
27
  def requirement
11
28
  self.class.requirement
12
29
  end