lite-validation 0.0.1

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 (138) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +94 -0
  3. data/Gemfile +18 -0
  4. data/README.md +770 -0
  5. data/bench/calibrational.rb +89 -0
  6. data/bench/comparative.rb +197 -0
  7. data/bench/functional.rb +107 -0
  8. data/bench/profile.rb +45 -0
  9. data/lib/lite/validation/adapters/interfaces/dry.rb +29 -0
  10. data/lib/lite/validation/error.rb +9 -0
  11. data/lib/lite/validation/result/abstract/disputable.rb +17 -0
  12. data/lib/lite/validation/result/abstract/failure.rb +19 -0
  13. data/lib/lite/validation/result/abstract/refutable.rb +21 -0
  14. data/lib/lite/validation/result/abstract/success.rb +25 -0
  15. data/lib/lite/validation/result/abstract.rb +16 -0
  16. data/lib/lite/validation/structured_error/record.rb +36 -0
  17. data/lib/lite/validation/structured_error.rb +23 -0
  18. data/lib/lite/validation/validator/adapters/errors/default.rb +24 -0
  19. data/lib/lite/validation/validator/adapters/interfaces/default.rb +32 -0
  20. data/lib/lite/validation/validator/adapters/interfaces/dry.rb +17 -0
  21. data/lib/lite/validation/validator/adapters/predicates/dry/adapter.rb +50 -0
  22. data/lib/lite/validation/validator/adapters/predicates/dry/builder.rb +46 -0
  23. data/lib/lite/validation/validator/adapters/predicates/dry/engine.rb +32 -0
  24. data/lib/lite/validation/validator/adapters/predicates/dry.rb +3 -0
  25. data/lib/lite/validation/validator/coordinator/builder.rb +92 -0
  26. data/lib/lite/validation/validator/coordinator/default.rb +32 -0
  27. data/lib/lite/validation/validator/coordinator/errors/builder.rb +56 -0
  28. data/lib/lite/validation/validator/coordinator/errors/dry.rb +29 -0
  29. data/lib/lite/validation/validator/coordinator/errors/flat.rb +46 -0
  30. data/lib/lite/validation/validator/coordinator/errors/hierarchical.rb +29 -0
  31. data/lib/lite/validation/validator/coordinator/instance.rb +30 -0
  32. data/lib/lite/validation/validator/coordinator.rb +12 -0
  33. data/lib/lite/validation/validator/helpers/path.rb +49 -0
  34. data/lib/lite/validation/validator/node/abstract/branch.rb +21 -0
  35. data/lib/lite/validation/validator/node/abstract/instance.rb +43 -0
  36. data/lib/lite/validation/validator/node/abstract/leaf.rb +35 -0
  37. data/lib/lite/validation/validator/node/abstract.rb +25 -0
  38. data/lib/lite/validation/validator/node/child.rb +44 -0
  39. data/lib/lite/validation/validator/node/implementation/apply_ruling.rb +44 -0
  40. data/lib/lite/validation/validator/node/implementation/dig.rb +38 -0
  41. data/lib/lite/validation/validator/node/implementation/helpers/call_foreign.rb +31 -0
  42. data/lib/lite/validation/validator/node/implementation/helpers/with_result.rb +23 -0
  43. data/lib/lite/validation/validator/node/implementation/helpers/yield_strategy.rb +83 -0
  44. data/lib/lite/validation/validator/node/implementation/helpers/yield_validator.rb +49 -0
  45. data/lib/lite/validation/validator/node/implementation/identity.rb +90 -0
  46. data/lib/lite/validation/validator/node/implementation/iteration/iterator.rb +102 -0
  47. data/lib/lite/validation/validator/node/implementation/iteration.rb +46 -0
  48. data/lib/lite/validation/validator/node/implementation/navigation.rb +43 -0
  49. data/lib/lite/validation/validator/node/implementation/predication.rb +61 -0
  50. data/lib/lite/validation/validator/node/implementation/scoping/evaluator.rb +43 -0
  51. data/lib/lite/validation/validator/node/implementation/scoping.rb +43 -0
  52. data/lib/lite/validation/validator/node/implementation/validation.rb +64 -0
  53. data/lib/lite/validation/validator/node/implementation/wrap.rb +26 -0
  54. data/lib/lite/validation/validator/node/root.rb +60 -0
  55. data/lib/lite/validation/validator/node/suspended.rb +33 -0
  56. data/lib/lite/validation/validator/node.rb +12 -0
  57. data/lib/lite/validation/validator/option/none.rb +43 -0
  58. data/lib/lite/validation/validator/option/some/abstract.rb +29 -0
  59. data/lib/lite/validation/validator/option/some/complex/registry/abstract.rb +67 -0
  60. data/lib/lite/validation/validator/option/some/complex/registry/node.rb +47 -0
  61. data/lib/lite/validation/validator/option/some/complex/registry/root.rb +31 -0
  62. data/lib/lite/validation/validator/option/some/complex/registry.rb +32 -0
  63. data/lib/lite/validation/validator/option/some/complex/wrappers/abstract/iterable.rb +31 -0
  64. data/lib/lite/validation/validator/option/some/complex/wrappers/abstract/non_iterable.rb +27 -0
  65. data/lib/lite/validation/validator/option/some/complex/wrappers/abstract.rb +35 -0
  66. data/lib/lite/validation/validator/option/some/complex/wrappers/array.rb +41 -0
  67. data/lib/lite/validation/validator/option/some/complex/wrappers/hash.rb +40 -0
  68. data/lib/lite/validation/validator/option/some/complex/wrappers/object.rb +34 -0
  69. data/lib/lite/validation/validator/option/some/complex/wrappers/tuple.rb +47 -0
  70. data/lib/lite/validation/validator/option/some/complex/wrappers.rb +5 -0
  71. data/lib/lite/validation/validator/option/some/complex.rb +24 -0
  72. data/lib/lite/validation/validator/option/some/dig.rb +34 -0
  73. data/lib/lite/validation/validator/option/some/simple.rb +23 -0
  74. data/lib/lite/validation/validator/option/some/singular.rb +29 -0
  75. data/lib/lite/validation/validator/option/some.rb +20 -0
  76. data/lib/lite/validation/validator/option.rb +20 -0
  77. data/lib/lite/validation/validator/predicate/abstract/variants.rb +23 -0
  78. data/lib/lite/validation/validator/predicate/foreign/adapter/input/single.rb +21 -0
  79. data/lib/lite/validation/validator/predicate/foreign/adapter/input/tuple.rb +21 -0
  80. data/lib/lite/validation/validator/predicate/foreign/adapter/input.rb +28 -0
  81. data/lib/lite/validation/validator/predicate/foreign/adapter/ruling/instance.rb +37 -0
  82. data/lib/lite/validation/validator/predicate/foreign/adapter/ruling.rb +26 -0
  83. data/lib/lite/validation/validator/predicate/foreign/engine.rb +27 -0
  84. data/lib/lite/validation/validator/predicate/foreign/variant.rb +33 -0
  85. data/lib/lite/validation/validator/predicate/foreign/variants.rb +46 -0
  86. data/lib/lite/validation/validator/predicate/native/builder.rb +72 -0
  87. data/lib/lite/validation/validator/predicate/native/definite.rb +19 -0
  88. data/lib/lite/validation/validator/predicate/native/instance.rb +41 -0
  89. data/lib/lite/validation/validator/predicate/native/optional.rb +34 -0
  90. data/lib/lite/validation/validator/predicate/registry.rb +47 -0
  91. data/lib/lite/validation/validator/predicate.rb +17 -0
  92. data/lib/lite/validation/validator/result/abstract/failure.rb +21 -0
  93. data/lib/lite/validation/validator/result/abstract/instance.rb +18 -0
  94. data/lib/lite/validation/validator/result/abstract/success.rb +17 -0
  95. data/lib/lite/validation/validator/result/abstract.rb +29 -0
  96. data/lib/lite/validation/validator/result/committed.rb +75 -0
  97. data/lib/lite/validation/validator/result/disputable/hash.rb +17 -0
  98. data/lib/lite/validation/validator/result/disputable/instance.rb +43 -0
  99. data/lib/lite/validation/validator/result/disputable/iterable/array.rb +23 -0
  100. data/lib/lite/validation/validator/result/disputable/iterable.rb +17 -0
  101. data/lib/lite/validation/validator/result/disputable/navigable.rb +35 -0
  102. data/lib/lite/validation/validator/result/disputable.rb +14 -0
  103. data/lib/lite/validation/validator/result/disputed/abstract/hash.rb +32 -0
  104. data/lib/lite/validation/validator/result/disputed/abstract/instance.rb +26 -0
  105. data/lib/lite/validation/validator/result/disputed/iterable/array.rb +42 -0
  106. data/lib/lite/validation/validator/result/disputed/iterable/hash.rb +38 -0
  107. data/lib/lite/validation/validator/result/disputed/iterable.rb +20 -0
  108. data/lib/lite/validation/validator/result/disputed/navigable.rb +59 -0
  109. data/lib/lite/validation/validator/result/disputed.rb +17 -0
  110. data/lib/lite/validation/validator/result/refuted.rb +78 -0
  111. data/lib/lite/validation/validator/result/valid/abstract/collect.rb +42 -0
  112. data/lib/lite/validation/validator/result/valid/abstract/commit.rb +25 -0
  113. data/lib/lite/validation/validator/result/valid/abstract/instance.rb +23 -0
  114. data/lib/lite/validation/validator/result/valid/iterable/array/abstract.rb +24 -0
  115. data/lib/lite/validation/validator/result/valid/iterable/array/tuples.rb +64 -0
  116. data/lib/lite/validation/validator/result/valid/iterable/array/values.rb +42 -0
  117. data/lib/lite/validation/validator/result/valid/iterable/hash.rb +46 -0
  118. data/lib/lite/validation/validator/result/valid/iterable.rb +33 -0
  119. data/lib/lite/validation/validator/result/valid/navigable.rb +68 -0
  120. data/lib/lite/validation/validator/result/valid.rb +21 -0
  121. data/lib/lite/validation/validator/result.rb +15 -0
  122. data/lib/lite/validation/validator/ruling/abstract/invalid.rb +59 -0
  123. data/lib/lite/validation/validator/ruling/abstract/valid.rb +23 -0
  124. data/lib/lite/validation/validator/ruling/abstract.rb +12 -0
  125. data/lib/lite/validation/validator/ruling/commit.rb +17 -0
  126. data/lib/lite/validation/validator/ruling/dispute.rb +21 -0
  127. data/lib/lite/validation/validator/ruling/invalidate.rb +32 -0
  128. data/lib/lite/validation/validator/ruling/pass.rb +19 -0
  129. data/lib/lite/validation/validator/ruling/refute.rb +21 -0
  130. data/lib/lite/validation/validator/ruling.rb +53 -0
  131. data/lib/lite/validation/validator/state/instance.rb +46 -0
  132. data/lib/lite/validation/validator/state/merge_strategy.rb +50 -0
  133. data/lib/lite/validation/validator/state/unwrap_strategy.rb +31 -0
  134. data/lib/lite/validation/validator/state.rb +21 -0
  135. data/lib/lite/validation/validator.rb +15 -0
  136. data/lib/lite/validation/version.rb +9 -0
  137. data/lib/lite/validation.rb +8 -0
  138. metadata +196 -0
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'instance'
4
+ require_relative '../../ruling'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Predicate
10
+ module Native
11
+ class Optional < Instance
12
+ Lite::Data.define(self, kwargs: [:definite])
13
+
14
+ def optional
15
+ self
16
+ end
17
+
18
+ def dispute
19
+ with(severity: :dispute, definite: definite&.dispute)
20
+ end
21
+
22
+ def refute
23
+ with(severity: :refute, definite: definite&.refute)
24
+ end
25
+
26
+ def validate_value(value)
27
+ definite.call(value)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../error'
4
+ require_relative 'abstract/variants'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Predicate
10
+ module Registry
11
+ def self.register_predicate(key, predicate)
12
+ raise Error, "Not a predicate: #{predicate}" unless predicate.is_a?(Predicate::Abstract::Variants)
13
+ raise Error, "Key already taken: #{key}" if predicates.key?(key)
14
+
15
+ predicates[key] = predicate
16
+ end
17
+
18
+ def self.predicate(key)
19
+ raise Error, "Predicate not registered: #{key}" unless predicates.key?(key)
20
+
21
+ predicates[key]
22
+ end
23
+
24
+ def self.predicates
25
+ @predicates ||= {}
26
+ end
27
+
28
+ def self.register_adapter(key, engine)
29
+ raise Error, "Key already taken: #{key}" if engines.key?(key)
30
+
31
+ engines[key] = engine
32
+ end
33
+
34
+ def self.engine(key)
35
+ raise Error, "Engine not registered: #{key}" unless engines.key?(key)
36
+
37
+ engines[key]
38
+ end
39
+
40
+ def self.engines
41
+ @engines ||= {}
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'predicate/registry'
4
+ require_relative 'predicate/native/builder'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Predicate
10
+ def self.define(name, &block)
11
+ predicate = Native::Builder.define(&block)
12
+ Registry.register_predicate(name, predicate)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../abstract'
4
+
5
+ module Lite
6
+ module Validation
7
+ module Validator
8
+ module Result
9
+ module Abstract
10
+ module Failure
11
+ include Validation::Result::Abstract::Failure
12
+
13
+ def to_failure(coordinator)
14
+ coordinator.build_final_error(self)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../abstract'
4
+ require 'lite/data'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Abstract
11
+ class Instance
12
+ include Abstract
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../abstract'
4
+
5
+ module Lite
6
+ module Validation
7
+ module Validator
8
+ module Result
9
+ module Abstract
10
+ module Success
11
+ include Validation::Result::Abstract::Success
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../result/abstract'
4
+ require_relative '../../result/abstract/disputable'
5
+ require_relative '../../result/abstract/refutable'
6
+ require_relative '../../error'
7
+
8
+ module Lite
9
+ module Validation
10
+ module Validator
11
+ module Result
12
+ module Abstract
13
+ include Validation::Result::Abstract
14
+ include Validation::Result::Abstract::Disputable
15
+ include Validation::Result::Abstract::Refutable
16
+
17
+ EMPTY = {}.freeze
18
+
19
+ private
20
+
21
+ def signature(name, data)
22
+ full_name = "Result::#{name}"
23
+ "#<#{[full_name, data].compact.join(' ')}>"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abstract/instance'
4
+ require_relative 'abstract/success'
5
+ require_relative '../option'
6
+
7
+ module Lite
8
+ module Validation
9
+ module Validator
10
+ module Result
11
+ class Committed < Abstract::Instance
12
+ include Abstract::Success
13
+
14
+ Lite::Data.define(self, args: %i[value])
15
+
16
+ def self.instance(value, *args)
17
+ new(value, *args)
18
+ end
19
+
20
+ private_class_method :new
21
+
22
+ def success_at?(*_path)
23
+ true
24
+ end
25
+
26
+ def committed?
27
+ true
28
+ end
29
+
30
+ def refuted?
31
+ false
32
+ end
33
+
34
+ def commit(*)
35
+ prevent_reopening!
36
+ end
37
+
38
+ def auto_commit(as:)
39
+ prevent_reopening!
40
+ end
41
+
42
+ def dispute(_error)
43
+ prevent_reopening!
44
+ end
45
+
46
+ def refute(_error)
47
+ prevent_reopening!
48
+ end
49
+
50
+ def navigate(*_path, &_block)
51
+ prevent_reopening!
52
+ end
53
+
54
+ def success
55
+ Option.some(value)
56
+ end
57
+
58
+ def inspect
59
+ signature('Committed', "value=#{value}")
60
+ end
61
+
62
+ private
63
+
64
+ def recurse(*_path, &_block)
65
+ prevent_reopening!
66
+ end
67
+
68
+ def prevent_reopening!
69
+ raise Error::Fatal, "Can't reopen committed result"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Validation
5
+ module Validator
6
+ module Result
7
+ module Disputable
8
+ module Hash
9
+ def child(key)
10
+ children[key] || Result.valid
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../abstract/instance'
4
+ require_relative '../refuted'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputable
11
+ class Instance < Abstract::Instance
12
+ Lite::Data.define(self, args: %i[children])
13
+
14
+ private_class_method :new
15
+
16
+ def committed?
17
+ false
18
+ end
19
+
20
+ def refuted?
21
+ false
22
+ end
23
+
24
+ def refute(error, fall_through: false)
25
+ Refuted.instance(error, fall_through: fall_through)
26
+ end
27
+
28
+ private
29
+
30
+ def enter(key, *rest, &block)
31
+ child = child(key)
32
+ result, meta = child.navigate(*rest, &block)
33
+ return [self, meta] if child.equal?(result)
34
+ return [result, meta] if result.refuted? && result.fall_through
35
+
36
+ [merge(result, key), meta]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../iterable'
4
+
5
+ module Lite
6
+ module Validation
7
+ module Validator
8
+ module Result
9
+ module Disputable
10
+ module Iterable
11
+ module Array
12
+ include Iterable
13
+
14
+ def child(_key)
15
+ Result.valid
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Validation
5
+ module Validator
6
+ module Result
7
+ module Disputable
8
+ module Iterable
9
+ def navigate(key, &block)
10
+ enter(key, &block)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'hash'
4
+
5
+ module Lite
6
+ module Validation
7
+ module Validator
8
+ module Result
9
+ module Disputable
10
+ module Navigable
11
+ include Hash
12
+
13
+ def success_at?(*path)
14
+ if path.empty?
15
+ success?
16
+ else
17
+ key, *rest = path
18
+ child(key).success_at?(*rest)
19
+ end
20
+ end
21
+
22
+ def navigate(*path, &block)
23
+ if path.empty?
24
+ block.call(self)
25
+ else
26
+ key, *rest = path
27
+ enter(key, *rest, &block)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'abstract/instance'
4
+
5
+ module Lite
6
+ module Validation
7
+ module Validator
8
+ module Result
9
+ module Disputable
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'instance'
4
+ require_relative '../../disputable/hash'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputed
11
+ module Abstract
12
+ class Hash < Abstract::Instance
13
+ include Disputable::Hash
14
+
15
+ Lite::Data.define(self, args: %i[errors_root])
16
+
17
+ def append(result, key)
18
+ raise Error::Fatal, "Key already taken #{key}" if children.key? key
19
+
20
+ super
21
+ end
22
+
23
+ def signature(class_name)
24
+ super(class_name, " with #{errors_root.count} root errors, #{children.count} children")
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../abstract/failure'
4
+ require_relative '../../disputable/instance'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputed
11
+ module Abstract
12
+ class Instance < Disputable::Instance
13
+ include Result::Abstract::Failure
14
+
15
+ def append(result, key)
16
+ raise Error::Fatal, "Can't append successful result: #{result.inspect}" if result.success?
17
+
18
+ merge(result, key)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../abstract/instance'
4
+ require_relative '../../disputable/iterable/array'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputed
11
+ module Iterable
12
+ class Array < Abstract::Instance
13
+ include Disputable::Iterable::Array
14
+
15
+ def self.instance(*args)
16
+ new([], *args)
17
+ end
18
+
19
+ def inspect
20
+ signature('Disputed::Iterable::Array')
21
+ end
22
+
23
+ def navigable
24
+ Disputed.navigable([], children.to_h)
25
+ end
26
+
27
+ def signature(class_name)
28
+ super(class_name, " with #{children.count} children")
29
+ end
30
+
31
+ def merge(result, key)
32
+ children << [key, result] unless result.success?
33
+
34
+ self
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../abstract/hash'
4
+ require_relative '../../disputable/iterable'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputed
11
+ module Iterable
12
+ class Hash < Abstract::Hash
13
+ include Disputable::Iterable
14
+
15
+ def self.instance(errors, children)
16
+ new(errors.dup, children.dup)
17
+ end
18
+
19
+ def inspect
20
+ signature('Disputed::Iterable::Hash')
21
+ end
22
+
23
+ def navigable
24
+ Disputed.navigable(errors_root, children)
25
+ end
26
+
27
+ def merge(result, key)
28
+ children.merge!(key => result) unless result.success?
29
+
30
+ self
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'iterable/array'
4
+ require_relative 'iterable/hash'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputed
11
+ module Iterable
12
+ def self.initial
13
+ Array.instance
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'iterable'
4
+ require_relative '../disputable/navigable'
5
+
6
+ module Lite
7
+ module Validation
8
+ module Validator
9
+ module Result
10
+ module Disputed
11
+ class Navigable < Abstract::Hash
12
+ include Disputable::Navigable
13
+
14
+ def self.instance(*args, error: nil)
15
+ instance = new([], EMPTY, *args)
16
+ error ? instance.dispute(error) : instance
17
+ end
18
+
19
+ def initialize(errors, children, *args)
20
+ super(errors.freeze, children.freeze, *args)
21
+ end
22
+
23
+ def commit(_value)
24
+ self
25
+ end
26
+
27
+ def auto_commit(as:)
28
+ self
29
+ end
30
+
31
+ def dispute(error)
32
+ raise Error::Fatal, "Structured error expected, got: #{error.inspect}" unless error.is_a?(StructuredError)
33
+
34
+ self.class.send :new, [*errors_root, error], children
35
+ end
36
+
37
+ def inspect
38
+ signature('Disputed::Navigable')
39
+ end
40
+
41
+ def iterable(commit:)
42
+ Iterable::Hash.instance(errors_root, children)
43
+ end
44
+
45
+ def merge(result, key)
46
+ return self if result.success?
47
+
48
+ self.class.send(
49
+ :new,
50
+ errors_root,
51
+ children.merge(key => result)
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'disputed/navigable'
4
+
5
+ module Lite
6
+ module Validation
7
+ module Validator
8
+ module Result
9
+ module Disputed
10
+ def self.navigable(errors, children)
11
+ Disputed::Navigable.send(:new, errors, children)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end