dry-types 0.14.1 → 1.5.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 +4 -4
- data/CHANGELOG.md +631 -134
- data/LICENSE +17 -17
- data/README.md +15 -13
- data/dry-types.gemspec +27 -30
- data/lib/dry/types/any.rb +32 -12
- data/lib/dry/types/array/constructor.rb +32 -0
- data/lib/dry/types/array/member.rb +75 -16
- data/lib/dry/types/array.rb +19 -6
- data/lib/dry/types/builder.rb +131 -15
- data/lib/dry/types/builder_methods.rb +49 -20
- data/lib/dry/types/coercions/json.rb +43 -7
- data/lib/dry/types/coercions/params.rb +118 -31
- data/lib/dry/types/coercions.rb +76 -22
- data/lib/dry/types/compat.rb +0 -2
- data/lib/dry/types/compiler.rb +56 -41
- data/lib/dry/types/constrained/coercible.rb +36 -6
- data/lib/dry/types/constrained.rb +81 -32
- data/lib/dry/types/constraints.rb +18 -4
- data/lib/dry/types/constructor/function.rb +216 -0
- data/lib/dry/types/constructor/wrapper.rb +94 -0
- data/lib/dry/types/constructor.rb +126 -56
- data/lib/dry/types/container.rb +7 -0
- data/lib/dry/types/core.rb +54 -21
- data/lib/dry/types/decorator.rb +38 -17
- data/lib/dry/types/default.rb +61 -16
- data/lib/dry/types/enum.rb +43 -20
- data/lib/dry/types/errors.rb +75 -9
- data/lib/dry/types/extensions/maybe.rb +74 -16
- data/lib/dry/types/extensions/monads.rb +29 -0
- data/lib/dry/types/extensions.rb +7 -1
- data/lib/dry/types/fn_container.rb +6 -1
- data/lib/dry/types/hash/constructor.rb +33 -0
- data/lib/dry/types/hash.rb +86 -67
- data/lib/dry/types/inflector.rb +3 -1
- data/lib/dry/types/json.rb +18 -16
- data/lib/dry/types/lax.rb +75 -0
- data/lib/dry/types/map.rb +76 -33
- data/lib/dry/types/meta.rb +51 -0
- data/lib/dry/types/module.rb +120 -0
- data/lib/dry/types/nominal.rb +210 -0
- data/lib/dry/types/options.rb +13 -26
- data/lib/dry/types/params.rb +39 -25
- data/lib/dry/types/predicate_inferrer.rb +238 -0
- data/lib/dry/types/predicate_registry.rb +34 -0
- data/lib/dry/types/primitive_inferrer.rb +97 -0
- data/lib/dry/types/printable.rb +16 -0
- data/lib/dry/types/printer.rb +315 -0
- data/lib/dry/types/result.rb +29 -3
- data/lib/dry/types/schema/key.rb +156 -0
- data/lib/dry/types/schema.rb +408 -0
- data/lib/dry/types/spec/types.rb +103 -33
- data/lib/dry/types/sum.rb +84 -35
- data/lib/dry/types/type.rb +49 -0
- data/lib/dry/types/version.rb +3 -1
- data/lib/dry/types.rb +156 -76
- data/lib/dry-types.rb +3 -1
- metadata +65 -78
- data/.gitignore +0 -10
- data/.rspec +0 -2
- data/.travis.yml +0 -27
- data/.yardopts +0 -5
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -24
- data/Rakefile +0 -20
- data/benchmarks/hash_schemas.rb +0 -51
- data/lib/dry/types/compat/form_types.rb +0 -27
- data/lib/dry/types/compat/int.rb +0 -14
- data/lib/dry/types/definition.rb +0 -113
- data/lib/dry/types/hash/schema.rb +0 -199
- data/lib/dry/types/hash/schema_builder.rb +0 -75
- data/lib/dry/types/safe.rb +0 -59
- data/log/.gitkeep +0 -0
data/lib/dry/types/json.rb
CHANGED
@@ -1,33 +1,35 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types/coercions/json"
|
2
4
|
|
3
5
|
module Dry
|
4
6
|
module Types
|
5
|
-
register(
|
6
|
-
self[
|
7
|
+
register("json.nil") do
|
8
|
+
self["nominal.nil"].constructor(Coercions::JSON.method(:to_nil))
|
7
9
|
end
|
8
10
|
|
9
|
-
register(
|
10
|
-
self[
|
11
|
+
register("json.date") do
|
12
|
+
self["nominal.date"].constructor(Coercions::JSON.method(:to_date))
|
11
13
|
end
|
12
14
|
|
13
|
-
register(
|
14
|
-
self[
|
15
|
+
register("json.date_time") do
|
16
|
+
self["nominal.date_time"].constructor(Coercions::JSON.method(:to_date_time))
|
15
17
|
end
|
16
18
|
|
17
|
-
register(
|
18
|
-
self[
|
19
|
+
register("json.time") do
|
20
|
+
self["nominal.time"].constructor(Coercions::JSON.method(:to_time))
|
19
21
|
end
|
20
22
|
|
21
|
-
register(
|
22
|
-
self[
|
23
|
+
register("json.decimal") do
|
24
|
+
self["nominal.decimal"].constructor(Coercions::JSON.method(:to_decimal))
|
23
25
|
end
|
24
26
|
|
25
|
-
register(
|
26
|
-
self[
|
27
|
+
register("json.symbol") do
|
28
|
+
self["nominal.symbol"].constructor(Coercions::JSON.method(:to_symbol))
|
27
29
|
end
|
28
30
|
|
29
|
-
register(
|
30
|
-
|
31
|
-
|
31
|
+
register("json.array") { self["array"] }
|
32
|
+
|
33
|
+
register("json.hash") { self["hash"] }
|
32
34
|
end
|
33
35
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/deprecations"
|
4
|
+
require "dry/types/decorator"
|
5
|
+
|
6
|
+
module Dry
|
7
|
+
module Types
|
8
|
+
# Lax types rescue from type-related errors when constructors fail
|
9
|
+
#
|
10
|
+
# @api public
|
11
|
+
class Lax
|
12
|
+
include Type
|
13
|
+
include Decorator
|
14
|
+
include Builder
|
15
|
+
include Printable
|
16
|
+
include Dry::Equalizer(:type, inspect: false, immutable: true)
|
17
|
+
|
18
|
+
undef :options, :constructor, :<<, :>>, :prepend, :append
|
19
|
+
|
20
|
+
# @param [Object] input
|
21
|
+
#
|
22
|
+
# @return [Object]
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
def call(input)
|
26
|
+
type.call_safe(input) { |output = input| output }
|
27
|
+
end
|
28
|
+
alias_method :[], :call
|
29
|
+
alias_method :call_safe, :call
|
30
|
+
alias_method :call_unsafe, :call
|
31
|
+
|
32
|
+
# @param [Object] input
|
33
|
+
# @param [#call,nil] block
|
34
|
+
#
|
35
|
+
# @yieldparam [Failure] failure
|
36
|
+
# @yieldreturn [Result]
|
37
|
+
#
|
38
|
+
# @return [Result,Logic::Result]
|
39
|
+
#
|
40
|
+
# @api public
|
41
|
+
def try(input, &block)
|
42
|
+
type.try(input, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @see Nominal#to_ast
|
46
|
+
#
|
47
|
+
# @api public
|
48
|
+
def to_ast(meta: true)
|
49
|
+
[:lax, type.to_ast(meta: meta)]
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Lax]
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
def lax
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# @param [Object, Dry::Types::Constructor] response
|
62
|
+
#
|
63
|
+
# @return [Boolean]
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
def decorate?(response)
|
67
|
+
super || response.is_a?(type.constructor_type)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
extend ::Dry::Core::Deprecations[:'dry-types']
|
72
|
+
Safe = Lax
|
73
|
+
deprecate_constant(:Safe)
|
74
|
+
end
|
75
|
+
end
|
data/lib/dry/types/map.rb
CHANGED
@@ -1,91 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dry
|
2
4
|
module Types
|
3
|
-
|
4
|
-
|
5
|
+
# Homogeneous mapping. It describes a hash with unknown keys that match a certain type.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# type = Dry::Types['hash'].map(
|
9
|
+
# Dry::Types['integer'].constrained(gteq: 1, lteq: 10),
|
10
|
+
# Dry::Types['string']
|
11
|
+
# )
|
12
|
+
#
|
13
|
+
# type.(1 => 'right')
|
14
|
+
# # => {1 => 'right'}
|
15
|
+
#
|
16
|
+
# type.('1' => 'wrong')
|
17
|
+
# # Dry::Types::MapError: "1" violates constraints (type?(Integer, "1") AND gteq?(1, "1") AND lteq?(10, "1") failed)
|
18
|
+
#
|
19
|
+
# type.(11 => 'wrong')
|
20
|
+
# # Dry::Types::MapError: 11 violates constraints (lteq?(10, 11) failed)
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
class Map < Nominal
|
24
|
+
def initialize(_primitive, key_type: Types["any"], value_type: Types["any"], meta: EMPTY_HASH)
|
5
25
|
super(_primitive, key_type: key_type, value_type: value_type, meta: meta)
|
6
|
-
validate_options!
|
7
26
|
end
|
8
27
|
|
9
28
|
# @return [Type]
|
29
|
+
#
|
30
|
+
# @api public
|
10
31
|
def key_type
|
11
32
|
options[:key_type]
|
12
33
|
end
|
13
34
|
|
14
35
|
# @return [Type]
|
36
|
+
#
|
37
|
+
# @api public
|
15
38
|
def value_type
|
16
39
|
options[:value_type]
|
17
40
|
end
|
18
41
|
|
19
42
|
# @return [String]
|
43
|
+
#
|
44
|
+
# @api public
|
20
45
|
def name
|
21
46
|
"Map"
|
22
47
|
end
|
23
48
|
|
24
49
|
# @param [Hash] hash
|
50
|
+
#
|
25
51
|
# @return [Hash]
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
def call_unsafe(hash)
|
55
|
+
try(hash) { |failure|
|
56
|
+
raise MapError, failure.error.message
|
57
|
+
}.input
|
30
58
|
end
|
31
|
-
alias_method :[], :call
|
32
59
|
|
33
60
|
# @param [Hash] hash
|
34
|
-
#
|
35
|
-
|
36
|
-
|
61
|
+
#
|
62
|
+
# @return [Hash]
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
def call_safe(hash)
|
66
|
+
try(hash) { return yield }.input
|
37
67
|
end
|
38
|
-
alias_method :===, :valid?
|
39
68
|
|
40
69
|
# @param [Hash] hash
|
70
|
+
#
|
41
71
|
# @return [Result]
|
72
|
+
#
|
73
|
+
# @api public
|
42
74
|
def try(hash)
|
43
75
|
result = coerce(hash)
|
44
76
|
return result if result.success? || !block_given?
|
77
|
+
|
45
78
|
yield(result)
|
46
79
|
end
|
47
80
|
|
48
81
|
# @param meta [Boolean] Whether to dump the meta to the AST
|
82
|
+
#
|
49
83
|
# @return [Array] An AST representation
|
84
|
+
#
|
85
|
+
# @api public
|
50
86
|
def to_ast(meta: true)
|
51
87
|
[:map,
|
52
|
-
[key_type.to_ast(meta: true),
|
88
|
+
[key_type.to_ast(meta: true),
|
89
|
+
value_type.to_ast(meta: true),
|
53
90
|
meta ? self.meta : EMPTY_HASH]]
|
54
91
|
end
|
55
92
|
|
93
|
+
# @return [Boolean]
|
94
|
+
#
|
95
|
+
# @api public
|
96
|
+
def constrained?
|
97
|
+
value_type.constrained?
|
98
|
+
end
|
99
|
+
|
56
100
|
private
|
57
101
|
|
102
|
+
# @api private
|
58
103
|
def coerce(input)
|
59
|
-
|
60
|
-
|
61
|
-
|
104
|
+
unless primitive?(input)
|
105
|
+
return failure(
|
106
|
+
input, CoercionError.new("#{input.inspect} must be an instance of #{primitive}")
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
output = {}
|
111
|
+
failures = []
|
62
112
|
|
63
|
-
|
113
|
+
input.each do |k, v|
|
114
|
+
res_k = key_type.try(k)
|
115
|
+
res_v = value_type.try(v)
|
64
116
|
|
65
|
-
input.each do |k,v|
|
66
|
-
res_k = options[:key_type].try(k)
|
67
|
-
res_v = options[:value_type].try(v)
|
68
117
|
if res_k.failure?
|
69
|
-
failures <<
|
118
|
+
failures << res_k.error
|
70
119
|
elsif output.key?(res_k.input)
|
71
|
-
failures << "duplicate coerced hash key #{res_k.input.inspect}"
|
120
|
+
failures << CoercionError.new("duplicate coerced hash key #{res_k.input.inspect}")
|
72
121
|
elsif res_v.failure?
|
73
|
-
failures <<
|
122
|
+
failures << res_v.error
|
74
123
|
else
|
75
124
|
output[res_k.input] = res_v.input
|
76
125
|
end
|
77
126
|
end
|
78
127
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
def validate_options!
|
85
|
-
%i(key_type value_type).each do |opt|
|
86
|
-
type = send(opt)
|
87
|
-
next if type.is_a?(Type)
|
88
|
-
raise MapError, ":#{opt} must be a #{Type}, got: #{type.inspect}"
|
128
|
+
if failures.empty?
|
129
|
+
success(output)
|
130
|
+
else
|
131
|
+
failure(input, MultipleError.new(failures))
|
89
132
|
end
|
90
133
|
end
|
91
134
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Types
|
5
|
+
# Storage for meta-data
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
module Meta
|
9
|
+
def initialize(*args, meta: EMPTY_HASH, **options)
|
10
|
+
super(*args, **options)
|
11
|
+
@meta = meta.freeze
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param options [Hash] new_options
|
15
|
+
#
|
16
|
+
# @return [Type]
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def with(**options)
|
20
|
+
super(meta: @meta, **options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @overload meta
|
24
|
+
# @return [Hash] metadata associated with type
|
25
|
+
#
|
26
|
+
# @overload meta(data)
|
27
|
+
# @param [Hash] new metadata to merge into existing metadata
|
28
|
+
# @return [Type] new type with added metadata
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
def meta(data = Undefined)
|
32
|
+
if Undefined.equal?(data)
|
33
|
+
@meta
|
34
|
+
elsif data.empty?
|
35
|
+
self
|
36
|
+
else
|
37
|
+
with(meta: @meta.merge(data))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Resets meta
|
42
|
+
#
|
43
|
+
# @return [Dry::Types::Type]
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
def pristine
|
47
|
+
with(meta: EMPTY_HASH)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/deprecations"
|
4
|
+
require "dry/types/builder_methods"
|
5
|
+
|
6
|
+
module Dry
|
7
|
+
module Types
|
8
|
+
# Export types registered in a container as module constants.
|
9
|
+
# @example
|
10
|
+
# module Types
|
11
|
+
# include Dry::Types(:strict, :coercible, :nominal, default: :strict)
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# Types.constants
|
15
|
+
# # => [:Class, :Strict, :Symbol, :Integer, :Float, :String, :Array, :Hash,
|
16
|
+
# # :Decimal, :Nil, :True, :False, :Bool, :Date, :Nominal, :DateTime, :Range,
|
17
|
+
# # :Coercible, :Time]
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
class Module < ::Module
|
21
|
+
def initialize(registry, *args, **kwargs)
|
22
|
+
@registry = registry
|
23
|
+
check_parameters(*args, **kwargs)
|
24
|
+
constants = type_constants(*args, **kwargs)
|
25
|
+
define_constants(constants)
|
26
|
+
extend(BuilderMethods)
|
27
|
+
|
28
|
+
if constants.key?(:Nominal)
|
29
|
+
singleton_class.send(:define_method, :included) do |base|
|
30
|
+
super(base)
|
31
|
+
base.instance_exec(const_get(:Nominal, false)) do |nominal|
|
32
|
+
extend Dry::Core::Deprecations[:'dry-types']
|
33
|
+
const_set(:Definition, nominal)
|
34
|
+
deprecate_constant(:Definition, message: "Nominal")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def type_constants(*namespaces, default: Undefined, **aliases)
|
42
|
+
if namespaces.empty? && aliases.empty? && Undefined.equal?(default)
|
43
|
+
default_ns = :Strict
|
44
|
+
elsif Undefined.equal?(default)
|
45
|
+
default_ns = Undefined
|
46
|
+
else
|
47
|
+
default_ns = Inflector.camelize(default).to_sym
|
48
|
+
end
|
49
|
+
|
50
|
+
tree = registry_tree
|
51
|
+
|
52
|
+
if namespaces.empty? && aliases.empty?
|
53
|
+
modules = tree.select { |_, v| v.is_a?(::Hash) }.map(&:first)
|
54
|
+
else
|
55
|
+
modules = (namespaces + aliases.keys).map { |n| Inflector.camelize(n).to_sym }
|
56
|
+
end
|
57
|
+
|
58
|
+
tree.each_with_object({}) do |(key, value), constants|
|
59
|
+
if modules.include?(key)
|
60
|
+
name = aliases.fetch(Inflector.underscore(key).to_sym, key)
|
61
|
+
constants[name] = value
|
62
|
+
end
|
63
|
+
|
64
|
+
constants.update(value) if key == default_ns
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api private
|
69
|
+
def registry_tree
|
70
|
+
@registry_tree ||= @registry.keys.each_with_object({}) { |key, tree|
|
71
|
+
type = @registry[key]
|
72
|
+
*modules, const_name = key.split(".").map { |part|
|
73
|
+
Inflector.camelize(part).to_sym
|
74
|
+
}
|
75
|
+
next if modules.empty?
|
76
|
+
|
77
|
+
modules.reduce(tree) { |br, name| br[name] ||= {} }[const_name] = type
|
78
|
+
}.freeze
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# @api private
|
84
|
+
def check_parameters(*namespaces, default: Undefined, **aliases)
|
85
|
+
referenced = namespaces.dup
|
86
|
+
referenced << default unless false.equal?(default) || Undefined.equal?(default)
|
87
|
+
referenced.concat(aliases.keys)
|
88
|
+
|
89
|
+
known = @registry.keys.map { |k|
|
90
|
+
ns, *path = k.split(".")
|
91
|
+
ns.to_sym unless path.empty?
|
92
|
+
}.compact.uniq
|
93
|
+
|
94
|
+
(referenced.uniq - known).each do |name|
|
95
|
+
raise ArgumentError,
|
96
|
+
"#{name.inspect} is not a known type namespace. "\
|
97
|
+
"Supported options are #{known.map(&:inspect).join(", ")}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# @api private
|
102
|
+
def define_constants(constants, mod = self)
|
103
|
+
constants.each do |name, value|
|
104
|
+
case value
|
105
|
+
when ::Hash
|
106
|
+
if mod.const_defined?(name, false)
|
107
|
+
define_constants(value, mod.const_get(name, false))
|
108
|
+
else
|
109
|
+
m = ::Module.new
|
110
|
+
mod.const_set(name, m)
|
111
|
+
define_constants(value, m)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
mod.const_set(name, value)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/deprecations"
|
4
|
+
require "dry/core/equalizer"
|
5
|
+
require "dry/types/builder"
|
6
|
+
require "dry/types/result"
|
7
|
+
require "dry/types/options"
|
8
|
+
require "dry/types/meta"
|
9
|
+
|
10
|
+
module Dry
|
11
|
+
module Types
|
12
|
+
# Nominal types define a primitive class and do not apply any constructors or constraints
|
13
|
+
#
|
14
|
+
# Use these types for annotations and the base for building more complex types on top of them.
|
15
|
+
#
|
16
|
+
# @api public
|
17
|
+
class Nominal
|
18
|
+
include Type
|
19
|
+
include Options
|
20
|
+
include Meta
|
21
|
+
include Builder
|
22
|
+
include Printable
|
23
|
+
include Dry::Equalizer(:primitive, :options, :meta, inspect: false, immutable: true)
|
24
|
+
|
25
|
+
# @return [Class]
|
26
|
+
attr_reader :primitive
|
27
|
+
|
28
|
+
# @param [Class] primitive
|
29
|
+
#
|
30
|
+
# @return [Type]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
def self.[](primitive)
|
34
|
+
if primitive == ::Array
|
35
|
+
Types::Array
|
36
|
+
elsif primitive == ::Hash
|
37
|
+
Types::Hash
|
38
|
+
else
|
39
|
+
self
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
ALWAYS = proc { true }
|
44
|
+
|
45
|
+
# @param [Type,Class] primitive
|
46
|
+
# @param [Hash] options
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
def initialize(primitive, **options)
|
50
|
+
super
|
51
|
+
@primitive = primitive
|
52
|
+
freeze
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [String]
|
56
|
+
#
|
57
|
+
# @api public
|
58
|
+
def name
|
59
|
+
primitive.name
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [false]
|
63
|
+
#
|
64
|
+
# @api public
|
65
|
+
def default?
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [false]
|
70
|
+
#
|
71
|
+
# @api public
|
72
|
+
def constrained?
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [false]
|
77
|
+
#
|
78
|
+
# @api public
|
79
|
+
def optional?
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param [BasicObject] input
|
84
|
+
#
|
85
|
+
# @return [BasicObject]
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
def call_unsafe(input)
|
89
|
+
input
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param [BasicObject] input
|
93
|
+
#
|
94
|
+
# @return [BasicObject]
|
95
|
+
#
|
96
|
+
# @api private
|
97
|
+
def call_safe(input)
|
98
|
+
input
|
99
|
+
end
|
100
|
+
|
101
|
+
# @param [Object] input
|
102
|
+
#
|
103
|
+
# @yieldparam [Failure] failure
|
104
|
+
# @yieldreturn [Result]
|
105
|
+
#
|
106
|
+
# @return [Result,Logic::Result] when a block is not provided
|
107
|
+
# @return [nil] otherwise
|
108
|
+
#
|
109
|
+
# @api public
|
110
|
+
def try(input)
|
111
|
+
success(input)
|
112
|
+
end
|
113
|
+
|
114
|
+
# @param (see Dry::Types::Success#initialize)
|
115
|
+
#
|
116
|
+
# @return [Result::Success]
|
117
|
+
#
|
118
|
+
# @api public
|
119
|
+
def success(input)
|
120
|
+
Result::Success.new(input)
|
121
|
+
end
|
122
|
+
|
123
|
+
# @param (see Failure#initialize)
|
124
|
+
#
|
125
|
+
# @return [Result::Failure]
|
126
|
+
#
|
127
|
+
# @api public
|
128
|
+
def failure(input, error)
|
129
|
+
raise ArgumentError, "error must be a CoercionError" unless error.is_a?(CoercionError)
|
130
|
+
|
131
|
+
Result::Failure.new(input, error)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Checks whether value is of a #primitive class
|
135
|
+
#
|
136
|
+
# @param [Object] value
|
137
|
+
#
|
138
|
+
# @return [Boolean]
|
139
|
+
#
|
140
|
+
# @api public
|
141
|
+
def primitive?(value)
|
142
|
+
value.is_a?(primitive)
|
143
|
+
end
|
144
|
+
|
145
|
+
# @api private
|
146
|
+
def coerce(input, &_block)
|
147
|
+
if primitive?(input)
|
148
|
+
input
|
149
|
+
elsif block_given?
|
150
|
+
yield
|
151
|
+
else
|
152
|
+
raise CoercionError, "#{input.inspect} must be an instance of #{primitive}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# @api private
|
157
|
+
def try_coerce(input)
|
158
|
+
result = success(input)
|
159
|
+
|
160
|
+
coerce(input) do
|
161
|
+
result = failure(
|
162
|
+
input,
|
163
|
+
CoercionError.new("#{input.inspect} must be an instance of #{primitive}")
|
164
|
+
)
|
165
|
+
end
|
166
|
+
|
167
|
+
if block_given?
|
168
|
+
yield(result)
|
169
|
+
else
|
170
|
+
result
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Return AST representation of a type nominal
|
175
|
+
#
|
176
|
+
# @return [Array]
|
177
|
+
#
|
178
|
+
# @api public
|
179
|
+
def to_ast(meta: true)
|
180
|
+
[:nominal, [primitive, meta ? self.meta : EMPTY_HASH]]
|
181
|
+
end
|
182
|
+
|
183
|
+
# Return self. Nominal types are lax by definition
|
184
|
+
#
|
185
|
+
# @return [Nominal]
|
186
|
+
#
|
187
|
+
# @api public
|
188
|
+
def lax
|
189
|
+
self
|
190
|
+
end
|
191
|
+
|
192
|
+
# Wrap the type with a proc
|
193
|
+
#
|
194
|
+
# @return [Proc]
|
195
|
+
#
|
196
|
+
# @api public
|
197
|
+
def to_proc
|
198
|
+
ALWAYS
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
extend Dry::Core::Deprecations[:'dry-types']
|
203
|
+
Definition = Nominal
|
204
|
+
deprecate_constant(:Definition, message: "Nominal")
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
require "dry/types/array"
|
209
|
+
require "dry/types/hash"
|
210
|
+
require "dry/types/map"
|