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.
- checksums.yaml +7 -0
- data/.rubocop.yml +94 -0
- data/Gemfile +18 -0
- data/README.md +770 -0
- data/bench/calibrational.rb +89 -0
- data/bench/comparative.rb +197 -0
- data/bench/functional.rb +107 -0
- data/bench/profile.rb +45 -0
- data/lib/lite/validation/adapters/interfaces/dry.rb +29 -0
- data/lib/lite/validation/error.rb +9 -0
- data/lib/lite/validation/result/abstract/disputable.rb +17 -0
- data/lib/lite/validation/result/abstract/failure.rb +19 -0
- data/lib/lite/validation/result/abstract/refutable.rb +21 -0
- data/lib/lite/validation/result/abstract/success.rb +25 -0
- data/lib/lite/validation/result/abstract.rb +16 -0
- data/lib/lite/validation/structured_error/record.rb +36 -0
- data/lib/lite/validation/structured_error.rb +23 -0
- data/lib/lite/validation/validator/adapters/errors/default.rb +24 -0
- data/lib/lite/validation/validator/adapters/interfaces/default.rb +32 -0
- data/lib/lite/validation/validator/adapters/interfaces/dry.rb +17 -0
- data/lib/lite/validation/validator/adapters/predicates/dry/adapter.rb +50 -0
- data/lib/lite/validation/validator/adapters/predicates/dry/builder.rb +46 -0
- data/lib/lite/validation/validator/adapters/predicates/dry/engine.rb +32 -0
- data/lib/lite/validation/validator/adapters/predicates/dry.rb +3 -0
- data/lib/lite/validation/validator/coordinator/builder.rb +92 -0
- data/lib/lite/validation/validator/coordinator/default.rb +32 -0
- data/lib/lite/validation/validator/coordinator/errors/builder.rb +56 -0
- data/lib/lite/validation/validator/coordinator/errors/dry.rb +29 -0
- data/lib/lite/validation/validator/coordinator/errors/flat.rb +46 -0
- data/lib/lite/validation/validator/coordinator/errors/hierarchical.rb +29 -0
- data/lib/lite/validation/validator/coordinator/instance.rb +30 -0
- data/lib/lite/validation/validator/coordinator.rb +12 -0
- data/lib/lite/validation/validator/helpers/path.rb +49 -0
- data/lib/lite/validation/validator/node/abstract/branch.rb +21 -0
- data/lib/lite/validation/validator/node/abstract/instance.rb +43 -0
- data/lib/lite/validation/validator/node/abstract/leaf.rb +35 -0
- data/lib/lite/validation/validator/node/abstract.rb +25 -0
- data/lib/lite/validation/validator/node/child.rb +44 -0
- data/lib/lite/validation/validator/node/implementation/apply_ruling.rb +44 -0
- data/lib/lite/validation/validator/node/implementation/dig.rb +38 -0
- data/lib/lite/validation/validator/node/implementation/helpers/call_foreign.rb +31 -0
- data/lib/lite/validation/validator/node/implementation/helpers/with_result.rb +23 -0
- data/lib/lite/validation/validator/node/implementation/helpers/yield_strategy.rb +83 -0
- data/lib/lite/validation/validator/node/implementation/helpers/yield_validator.rb +49 -0
- data/lib/lite/validation/validator/node/implementation/identity.rb +90 -0
- data/lib/lite/validation/validator/node/implementation/iteration/iterator.rb +102 -0
- data/lib/lite/validation/validator/node/implementation/iteration.rb +46 -0
- data/lib/lite/validation/validator/node/implementation/navigation.rb +43 -0
- data/lib/lite/validation/validator/node/implementation/predication.rb +61 -0
- data/lib/lite/validation/validator/node/implementation/scoping/evaluator.rb +43 -0
- data/lib/lite/validation/validator/node/implementation/scoping.rb +43 -0
- data/lib/lite/validation/validator/node/implementation/validation.rb +64 -0
- data/lib/lite/validation/validator/node/implementation/wrap.rb +26 -0
- data/lib/lite/validation/validator/node/root.rb +60 -0
- data/lib/lite/validation/validator/node/suspended.rb +33 -0
- data/lib/lite/validation/validator/node.rb +12 -0
- data/lib/lite/validation/validator/option/none.rb +43 -0
- data/lib/lite/validation/validator/option/some/abstract.rb +29 -0
- data/lib/lite/validation/validator/option/some/complex/registry/abstract.rb +67 -0
- data/lib/lite/validation/validator/option/some/complex/registry/node.rb +47 -0
- data/lib/lite/validation/validator/option/some/complex/registry/root.rb +31 -0
- data/lib/lite/validation/validator/option/some/complex/registry.rb +32 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/abstract/iterable.rb +31 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/abstract/non_iterable.rb +27 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/abstract.rb +35 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/array.rb +41 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/hash.rb +40 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/object.rb +34 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers/tuple.rb +47 -0
- data/lib/lite/validation/validator/option/some/complex/wrappers.rb +5 -0
- data/lib/lite/validation/validator/option/some/complex.rb +24 -0
- data/lib/lite/validation/validator/option/some/dig.rb +34 -0
- data/lib/lite/validation/validator/option/some/simple.rb +23 -0
- data/lib/lite/validation/validator/option/some/singular.rb +29 -0
- data/lib/lite/validation/validator/option/some.rb +20 -0
- data/lib/lite/validation/validator/option.rb +20 -0
- data/lib/lite/validation/validator/predicate/abstract/variants.rb +23 -0
- data/lib/lite/validation/validator/predicate/foreign/adapter/input/single.rb +21 -0
- data/lib/lite/validation/validator/predicate/foreign/adapter/input/tuple.rb +21 -0
- data/lib/lite/validation/validator/predicate/foreign/adapter/input.rb +28 -0
- data/lib/lite/validation/validator/predicate/foreign/adapter/ruling/instance.rb +37 -0
- data/lib/lite/validation/validator/predicate/foreign/adapter/ruling.rb +26 -0
- data/lib/lite/validation/validator/predicate/foreign/engine.rb +27 -0
- data/lib/lite/validation/validator/predicate/foreign/variant.rb +33 -0
- data/lib/lite/validation/validator/predicate/foreign/variants.rb +46 -0
- data/lib/lite/validation/validator/predicate/native/builder.rb +72 -0
- data/lib/lite/validation/validator/predicate/native/definite.rb +19 -0
- data/lib/lite/validation/validator/predicate/native/instance.rb +41 -0
- data/lib/lite/validation/validator/predicate/native/optional.rb +34 -0
- data/lib/lite/validation/validator/predicate/registry.rb +47 -0
- data/lib/lite/validation/validator/predicate.rb +17 -0
- data/lib/lite/validation/validator/result/abstract/failure.rb +21 -0
- data/lib/lite/validation/validator/result/abstract/instance.rb +18 -0
- data/lib/lite/validation/validator/result/abstract/success.rb +17 -0
- data/lib/lite/validation/validator/result/abstract.rb +29 -0
- data/lib/lite/validation/validator/result/committed.rb +75 -0
- data/lib/lite/validation/validator/result/disputable/hash.rb +17 -0
- data/lib/lite/validation/validator/result/disputable/instance.rb +43 -0
- data/lib/lite/validation/validator/result/disputable/iterable/array.rb +23 -0
- data/lib/lite/validation/validator/result/disputable/iterable.rb +17 -0
- data/lib/lite/validation/validator/result/disputable/navigable.rb +35 -0
- data/lib/lite/validation/validator/result/disputable.rb +14 -0
- data/lib/lite/validation/validator/result/disputed/abstract/hash.rb +32 -0
- data/lib/lite/validation/validator/result/disputed/abstract/instance.rb +26 -0
- data/lib/lite/validation/validator/result/disputed/iterable/array.rb +42 -0
- data/lib/lite/validation/validator/result/disputed/iterable/hash.rb +38 -0
- data/lib/lite/validation/validator/result/disputed/iterable.rb +20 -0
- data/lib/lite/validation/validator/result/disputed/navigable.rb +59 -0
- data/lib/lite/validation/validator/result/disputed.rb +17 -0
- data/lib/lite/validation/validator/result/refuted.rb +78 -0
- data/lib/lite/validation/validator/result/valid/abstract/collect.rb +42 -0
- data/lib/lite/validation/validator/result/valid/abstract/commit.rb +25 -0
- data/lib/lite/validation/validator/result/valid/abstract/instance.rb +23 -0
- data/lib/lite/validation/validator/result/valid/iterable/array/abstract.rb +24 -0
- data/lib/lite/validation/validator/result/valid/iterable/array/tuples.rb +64 -0
- data/lib/lite/validation/validator/result/valid/iterable/array/values.rb +42 -0
- data/lib/lite/validation/validator/result/valid/iterable/hash.rb +46 -0
- data/lib/lite/validation/validator/result/valid/iterable.rb +33 -0
- data/lib/lite/validation/validator/result/valid/navigable.rb +68 -0
- data/lib/lite/validation/validator/result/valid.rb +21 -0
- data/lib/lite/validation/validator/result.rb +15 -0
- data/lib/lite/validation/validator/ruling/abstract/invalid.rb +59 -0
- data/lib/lite/validation/validator/ruling/abstract/valid.rb +23 -0
- data/lib/lite/validation/validator/ruling/abstract.rb +12 -0
- data/lib/lite/validation/validator/ruling/commit.rb +17 -0
- data/lib/lite/validation/validator/ruling/dispute.rb +21 -0
- data/lib/lite/validation/validator/ruling/invalidate.rb +32 -0
- data/lib/lite/validation/validator/ruling/pass.rb +19 -0
- data/lib/lite/validation/validator/ruling/refute.rb +21 -0
- data/lib/lite/validation/validator/ruling.rb +53 -0
- data/lib/lite/validation/validator/state/instance.rb +46 -0
- data/lib/lite/validation/validator/state/merge_strategy.rb +50 -0
- data/lib/lite/validation/validator/state/unwrap_strategy.rb +31 -0
- data/lib/lite/validation/validator/state.rb +21 -0
- data/lib/lite/validation/validator.rb +15 -0
- data/lib/lite/validation/version.rb +9 -0
- data/lib/lite/validation.rb +8 -0
- metadata +196 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'abstract/iterable'
|
|
4
|
+
require_relative '../../singular'
|
|
5
|
+
|
|
6
|
+
module Lite
|
|
7
|
+
module Validation
|
|
8
|
+
module Validator
|
|
9
|
+
module Option
|
|
10
|
+
module Some
|
|
11
|
+
module Complex
|
|
12
|
+
module Wrappers
|
|
13
|
+
class Hash < Abstract::Iterable
|
|
14
|
+
include Singular
|
|
15
|
+
|
|
16
|
+
def fetch(key)
|
|
17
|
+
return Option.none unless value.key? key
|
|
18
|
+
|
|
19
|
+
Option.some(value[key])
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reduce(initial_state, &block)
|
|
23
|
+
value.lazy
|
|
24
|
+
.map { |key, value| [value, key] }
|
|
25
|
+
.reduce(initial_state, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def inspect
|
|
29
|
+
"#<Option::Some::Hash length=#{value.length}>"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Registry.register(::Hash, self)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'abstract/non_iterable'
|
|
4
|
+
require_relative '../../singular'
|
|
5
|
+
|
|
6
|
+
module Lite
|
|
7
|
+
module Validation
|
|
8
|
+
module Validator
|
|
9
|
+
module Option
|
|
10
|
+
module Some
|
|
11
|
+
module Complex
|
|
12
|
+
module Wrappers
|
|
13
|
+
class Object < Abstract::NonIterable
|
|
14
|
+
include Singular
|
|
15
|
+
|
|
16
|
+
def fetch(key)
|
|
17
|
+
Option.some(value.send(key))
|
|
18
|
+
rescue StandardError => e
|
|
19
|
+
raise InvalidAccess, e.message
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def inspect
|
|
23
|
+
"#<Option::Some::Object class=#{value.class.name}>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
Registry.register(::Object, self)
|
|
27
|
+
end
|
|
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 'abstract/non_iterable'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Option
|
|
9
|
+
module Some
|
|
10
|
+
module Complex
|
|
11
|
+
module Wrappers
|
|
12
|
+
class Tuple < Abstract::NonIterable
|
|
13
|
+
def some_or_nil
|
|
14
|
+
return self if some?
|
|
15
|
+
|
|
16
|
+
self.class.new(value.map(&:some_or_nil))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_option(coordinator)
|
|
20
|
+
value.map { _1.to_option(coordinator) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def unwrap
|
|
24
|
+
transpose.unwrap
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def transpose
|
|
28
|
+
return Option.none unless some?
|
|
29
|
+
|
|
30
|
+
Option.some(value.map(&:value))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def some?
|
|
34
|
+
value.all?(&:some?)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def inspect
|
|
38
|
+
"#<Option::Some::Tuple (#{value.map(&:inspect).join(', ')})>"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'complex/wrappers'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Option
|
|
9
|
+
module Some
|
|
10
|
+
module Complex
|
|
11
|
+
def self.instance(object)
|
|
12
|
+
return object if object.is_a?(Complex)
|
|
13
|
+
|
|
14
|
+
wrapper = Registry.wrapper_for(object.class)
|
|
15
|
+
raise Error::Fatal, "No wrapper for: #{object.class}" unless wrapper
|
|
16
|
+
|
|
17
|
+
wrapper.new(object)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'complex/wrappers/tuple'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Option
|
|
9
|
+
module Some
|
|
10
|
+
module Dig
|
|
11
|
+
def dig(paths)
|
|
12
|
+
if paths.length == 1
|
|
13
|
+
follow_path(paths.first)
|
|
14
|
+
else
|
|
15
|
+
tuple = paths.map { follow_path(_1) }
|
|
16
|
+
Complex::Wrappers::Tuple.new(tuple)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def follow_path(path)
|
|
23
|
+
path.reduce(self) do |option, key|
|
|
24
|
+
break option if option.none?
|
|
25
|
+
|
|
26
|
+
option.to_complex.fetch(key)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'abstract'
|
|
4
|
+
require_relative 'complex'
|
|
5
|
+
require_relative 'singular'
|
|
6
|
+
|
|
7
|
+
module Lite
|
|
8
|
+
module Validation
|
|
9
|
+
module Validator
|
|
10
|
+
module Option
|
|
11
|
+
module Some
|
|
12
|
+
class Simple < Abstract
|
|
13
|
+
include Singular
|
|
14
|
+
|
|
15
|
+
def to_complex
|
|
16
|
+
Complex.instance(value)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'dig'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Option
|
|
9
|
+
module Some
|
|
10
|
+
module Singular
|
|
11
|
+
include Dig
|
|
12
|
+
|
|
13
|
+
def some_or_nil
|
|
14
|
+
self
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_option(coordinator)
|
|
18
|
+
coordinator.some(value)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def unwrap
|
|
22
|
+
value
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lite/data'
|
|
4
|
+
|
|
5
|
+
require_relative 'some/simple'
|
|
6
|
+
require_relative 'some/complex'
|
|
7
|
+
|
|
8
|
+
module Lite
|
|
9
|
+
module Validation
|
|
10
|
+
module Validator
|
|
11
|
+
module Option
|
|
12
|
+
module Some
|
|
13
|
+
def self.instance(value)
|
|
14
|
+
Simple.new(value)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'option/some'
|
|
4
|
+
require_relative 'option/none'
|
|
5
|
+
|
|
6
|
+
module Lite
|
|
7
|
+
module Validation
|
|
8
|
+
module Validator
|
|
9
|
+
module Option
|
|
10
|
+
def self.some(value)
|
|
11
|
+
Some.instance(value)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.none
|
|
15
|
+
None
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../error'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Predicate
|
|
9
|
+
module Abstract
|
|
10
|
+
module Variants
|
|
11
|
+
def definite
|
|
12
|
+
raise Error::Fatal, 'Definite variant not available'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def optional
|
|
16
|
+
raise Error::Fatal, 'Optional variant not available'
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lite
|
|
4
|
+
module Validation
|
|
5
|
+
module Validator
|
|
6
|
+
module Predicate
|
|
7
|
+
module Foreign
|
|
8
|
+
module Adapter
|
|
9
|
+
module Input
|
|
10
|
+
module Single
|
|
11
|
+
def self.pass_in(value, block)
|
|
12
|
+
block.call(value)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lite
|
|
4
|
+
module Validation
|
|
5
|
+
module Validator
|
|
6
|
+
module Predicate
|
|
7
|
+
module Foreign
|
|
8
|
+
module Adapter
|
|
9
|
+
module Input
|
|
10
|
+
module Tuple
|
|
11
|
+
def self.pass_in(value, block)
|
|
12
|
+
block.call(*value)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../../error'
|
|
4
|
+
require_relative 'input/single'
|
|
5
|
+
require_relative 'input/tuple'
|
|
6
|
+
|
|
7
|
+
module Lite
|
|
8
|
+
module Validation
|
|
9
|
+
module Validator
|
|
10
|
+
module Predicate
|
|
11
|
+
module Foreign
|
|
12
|
+
module Adapter
|
|
13
|
+
module Input
|
|
14
|
+
def self.instance(arity)
|
|
15
|
+
raise Error::Fatal, "Arity must be positive integer, got: #{arity}" unless arity.positive?
|
|
16
|
+
|
|
17
|
+
case arity
|
|
18
|
+
when 1 then Single
|
|
19
|
+
else Tuple
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lite/data'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Predicate
|
|
9
|
+
module Foreign
|
|
10
|
+
module Adapter
|
|
11
|
+
module Ruling
|
|
12
|
+
class Instance
|
|
13
|
+
Lite::Data.define(self, args: %i[severity ruling_class])
|
|
14
|
+
|
|
15
|
+
def dispute
|
|
16
|
+
severity == :dispute ? self : Ruling.instance(:dispute)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def refute
|
|
20
|
+
severity == :refute ? self : Ruling.instance(:refute)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_ruling(error)
|
|
24
|
+
ruling_class.instance(error)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private_class_method :new
|
|
28
|
+
|
|
29
|
+
private :with
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../../ruling'
|
|
4
|
+
require_relative 'ruling/instance'
|
|
5
|
+
|
|
6
|
+
module Lite
|
|
7
|
+
module Validation
|
|
8
|
+
module Validator
|
|
9
|
+
module Predicate
|
|
10
|
+
module Foreign
|
|
11
|
+
module Adapter
|
|
12
|
+
module Ruling
|
|
13
|
+
def self.instance(severity)
|
|
14
|
+
case severity
|
|
15
|
+
when :dispute then @dispute ||= Instance.send(:new, :dispute, Validator::Ruling::Dispute)
|
|
16
|
+
when :refute then @refute ||= Instance.send(:new, :refute, Validator::Ruling::Refute)
|
|
17
|
+
else raise Validation::Error::Fatal, 'Unexpected severity'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'variants'
|
|
4
|
+
require_relative '../registry'
|
|
5
|
+
require_relative '../../ruling'
|
|
6
|
+
|
|
7
|
+
module Lite
|
|
8
|
+
module Validation
|
|
9
|
+
module Validator
|
|
10
|
+
module Predicate
|
|
11
|
+
module Foreign
|
|
12
|
+
class Engine
|
|
13
|
+
Lite::Data.define(self, args: [:error_adapter])
|
|
14
|
+
|
|
15
|
+
def build(_keys, &_block)
|
|
16
|
+
raise NotImplementedError, "#{self.class.name}##{__method__} unimplemented"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def build_contextual(_keys, _context, &_block)
|
|
20
|
+
raise NotImplementedError, "#{self.class.name}##{__method__} unimplemented"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lite/data'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Predicate
|
|
9
|
+
module Foreign
|
|
10
|
+
class Variant
|
|
11
|
+
Lite::Data.define(self, args: %i[callable adapter])
|
|
12
|
+
|
|
13
|
+
def call(value, _context)
|
|
14
|
+
adapter.to_ruling(adapter.pass_in(value, callable), callable, value)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def severity
|
|
18
|
+
adapter.severity
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dispute
|
|
22
|
+
severity == :dispute ? self : with(adapter: adapter.dispute)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def refute
|
|
26
|
+
severity == :refute ? self : with(adapter: adapter.refute)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../abstract/variants'
|
|
4
|
+
require_relative 'variant'
|
|
5
|
+
|
|
6
|
+
module Lite
|
|
7
|
+
module Validation
|
|
8
|
+
module Validator
|
|
9
|
+
module Predicate
|
|
10
|
+
module Foreign
|
|
11
|
+
class Variants
|
|
12
|
+
include Abstract::Variants
|
|
13
|
+
|
|
14
|
+
Lite::Data.define(self, kwargs: %i[definite optional])
|
|
15
|
+
|
|
16
|
+
def initialize(definite: nil, optional: nil)
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def definite
|
|
21
|
+
@definite || super
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def optional
|
|
25
|
+
@optional || super
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def dispute
|
|
29
|
+
with definite: definite&.dispute, optional: optional&.dispute
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def refute
|
|
33
|
+
with definite: definite&.refute, optional: optional&.refute
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def with(definite: self.definite, optional: self.optional)
|
|
37
|
+
return self if definite == self.definite && optional == self.optional
|
|
38
|
+
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'definite'
|
|
4
|
+
require_relative 'optional'
|
|
5
|
+
|
|
6
|
+
require_relative '../../coordinator/default'
|
|
7
|
+
require_relative '../../node/root'
|
|
8
|
+
require_relative '../../coordinator/errors/flat'
|
|
9
|
+
|
|
10
|
+
module Lite
|
|
11
|
+
module Validation
|
|
12
|
+
module Validator
|
|
13
|
+
module Predicate
|
|
14
|
+
module Native
|
|
15
|
+
class Builder
|
|
16
|
+
include Ruling::Constructors
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@validate_value = nil
|
|
20
|
+
@validate_option = nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.define(&block)
|
|
24
|
+
new.tap { _1.instance_eval(&block) }.build
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def validate_value(&block)
|
|
28
|
+
if block
|
|
29
|
+
raise(Error, 'Test value already set') unless @validate_value.nil?
|
|
30
|
+
|
|
31
|
+
@validate_value = block
|
|
32
|
+
|
|
33
|
+
else
|
|
34
|
+
@validate_value
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def validate_option(&block)
|
|
39
|
+
if block
|
|
40
|
+
raise(Error, 'Test option already set') unless @validate_option.nil?
|
|
41
|
+
|
|
42
|
+
@validate_option = block
|
|
43
|
+
else
|
|
44
|
+
@validate_option
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def build
|
|
49
|
+
result = validate
|
|
50
|
+
raise Error, "Builder invalid: #{result.error.message}" unless result.success?
|
|
51
|
+
|
|
52
|
+
definite = validate_value ? Native::Definite.new(validate_value) : nil
|
|
53
|
+
return definite if validate_option.nil?
|
|
54
|
+
|
|
55
|
+
Native::Optional.new(validate_option, definite: definite)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def validate
|
|
59
|
+
coordinator = Coordinator::Default.instance(Coordinator::Errors::Flat)
|
|
60
|
+
|
|
61
|
+
Validator::Node::Root.initial(self, coordinator).at do |builder|
|
|
62
|
+
builder.validate(%i[validate_option validate_value]) do |tuple|
|
|
63
|
+
Refute(coordinator.internal_error(:value_missing)) if tuple.all?(&:nil?)
|
|
64
|
+
end
|
|
65
|
+
end.to_result
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'instance'
|
|
4
|
+
|
|
5
|
+
module Lite
|
|
6
|
+
module Validation
|
|
7
|
+
module Validator
|
|
8
|
+
module Predicate
|
|
9
|
+
module Native
|
|
10
|
+
class Definite < Instance
|
|
11
|
+
def definite
|
|
12
|
+
self
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lite/data'
|
|
4
|
+
|
|
5
|
+
require_relative '../abstract/variants'
|
|
6
|
+
|
|
7
|
+
module Lite
|
|
8
|
+
module Validation
|
|
9
|
+
module Validator
|
|
10
|
+
module Predicate
|
|
11
|
+
module Native
|
|
12
|
+
class Instance
|
|
13
|
+
Lite::Data.define(self, args: [:proc], kwargs: [:severity])
|
|
14
|
+
include Ruling::Constructors
|
|
15
|
+
include Abstract::Variants
|
|
16
|
+
|
|
17
|
+
def initialize(proc, severity: nil)
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dispute
|
|
22
|
+
with(severity: :dispute)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def refute
|
|
26
|
+
with(severity: :refute)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def call(*args, **opts)
|
|
30
|
+
raise Error::Fatal, 'Level not set' unless severity
|
|
31
|
+
|
|
32
|
+
ruling = instance_exec(*args, **opts, &proc)
|
|
33
|
+
ruling = Pass() if ruling.nil?
|
|
34
|
+
ruling.invalid { |invalid| invalid.send(severity) }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|