dry-types 0.15.0 → 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 +547 -161
- data/LICENSE +17 -17
- data/README.md +15 -13
- data/dry-types.gemspec +27 -30
- data/lib/dry/types/any.rb +23 -12
- data/lib/dry/types/array/constructor.rb +32 -0
- data/lib/dry/types/array/member.rb +74 -15
- data/lib/dry/types/array.rb +18 -2
- data/lib/dry/types/builder.rb +118 -22
- data/lib/dry/types/builder_methods.rb +46 -16
- data/lib/dry/types/coercions/json.rb +43 -7
- data/lib/dry/types/coercions/params.rb +117 -32
- data/lib/dry/types/coercions.rb +76 -22
- data/lib/dry/types/compiler.rb +44 -21
- data/lib/dry/types/constrained/coercible.rb +36 -6
- data/lib/dry/types/constrained.rb +79 -31
- 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 +110 -61
- data/lib/dry/types/container.rb +6 -1
- data/lib/dry/types/core.rb +34 -11
- data/lib/dry/types/decorator.rb +38 -17
- data/lib/dry/types/default.rb +61 -16
- data/lib/dry/types/enum.rb +36 -20
- data/lib/dry/types/errors.rb +74 -8
- data/lib/dry/types/extensions/maybe.rb +65 -17
- 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 +17 -4
- data/lib/dry/types/hash.rb +32 -20
- 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 +70 -32
- data/lib/dry/types/meta.rb +51 -0
- data/lib/dry/types/module.rb +16 -11
- data/lib/dry/types/nominal.rb +113 -22
- data/lib/dry/types/options.rb +12 -25
- 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 +5 -1
- data/lib/dry/types/printer.rb +63 -57
- data/lib/dry/types/result.rb +29 -3
- data/lib/dry/types/schema/key.rb +62 -36
- data/lib/dry/types/schema.rb +201 -91
- data/lib/dry/types/spec/types.rb +99 -37
- data/lib/dry/types/sum.rb +75 -25
- data/lib/dry/types/type.rb +49 -0
- data/lib/dry/types/version.rb +3 -1
- data/lib/dry/types.rb +106 -48
- data/lib/dry-types.rb +3 -1
- metadata +55 -78
- data/.codeclimate.yml +0 -15
- data/.gitignore +0 -10
- data/.rspec +0 -2
- data/.rubocop.yml +0 -43
- data/.travis.yml +0 -28
- data/.yardopts +0 -5
- data/CONTRIBUTING.md +0 -29
- data/Gemfile +0 -23
- data/Rakefile +0 -20
- data/benchmarks/hash_schemas.rb +0 -51
- data/lib/dry/types/safe.rb +0 -61
- data/log/.gitkeep +0 -0
@@ -1,9 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
require "dry/types/fn_container"
|
5
|
+
require "dry/types/constructor/function"
|
6
|
+
require "dry/types/constructor/wrapper"
|
2
7
|
|
3
8
|
module Dry
|
4
9
|
module Types
|
10
|
+
# Constructor types apply a function to the input that is supposed to return
|
11
|
+
# a new value. Coercion is a common use case for constructor types.
|
12
|
+
#
|
13
|
+
# @api public
|
5
14
|
class Constructor < Nominal
|
6
|
-
include Dry::Equalizer(:type, :options, :
|
15
|
+
include Dry::Equalizer(:type, :options, inspect: false, immutable: true)
|
7
16
|
|
8
17
|
# @return [#call]
|
9
18
|
attr_reader :fn
|
@@ -11,135 +20,179 @@ module Dry
|
|
11
20
|
# @return [Type]
|
12
21
|
attr_reader :type
|
13
22
|
|
14
|
-
undef :constrained
|
23
|
+
undef :constrained?, :meta, :optional?, :primitive, :default?, :name
|
15
24
|
|
16
25
|
# @param [Builder, Object] input
|
17
26
|
# @param [Hash] options
|
18
27
|
# @param [#call, nil] block
|
28
|
+
#
|
29
|
+
# @api public
|
19
30
|
def self.new(input, **options, &block)
|
20
31
|
type = input.is_a?(Builder) ? input : Nominal.new(input)
|
21
|
-
super(type, **options,
|
32
|
+
super(type, **options, fn: Function[options.fetch(:fn, block)])
|
22
33
|
end
|
23
34
|
|
24
|
-
# @param [
|
35
|
+
# @param [Builder, Object] input
|
25
36
|
# @param [Hash] options
|
26
37
|
# @param [#call, nil] block
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
raise ArgumentError, 'Missing constructor block' if fn.nil?
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
def self.[](type, fn:, **options)
|
41
|
+
function = Function[fn]
|
32
42
|
|
33
|
-
|
43
|
+
if function.wrapper?
|
44
|
+
wrapper_type.new(type, fn: function, **options)
|
45
|
+
else
|
46
|
+
new(type, fn: function, **options)
|
47
|
+
end
|
34
48
|
end
|
35
49
|
|
36
|
-
# @
|
37
|
-
def
|
38
|
-
|
50
|
+
# @api private
|
51
|
+
def self.wrapper_type
|
52
|
+
@wrapper_type ||= begin
|
53
|
+
if self < Wrapper
|
54
|
+
self
|
55
|
+
else
|
56
|
+
const_set(:Wrapping, ::Class.new(self).include(Wrapper))
|
57
|
+
end
|
58
|
+
end
|
39
59
|
end
|
40
60
|
|
41
|
-
#
|
42
|
-
|
43
|
-
|
61
|
+
# Instantiate a new constructor type instance
|
62
|
+
#
|
63
|
+
# @param [Type] type
|
64
|
+
# @param [Function] fn
|
65
|
+
# @param [Hash] options
|
66
|
+
#
|
67
|
+
# @api private
|
68
|
+
def initialize(type, fn: nil, **options)
|
69
|
+
@type = type
|
70
|
+
@fn = fn
|
71
|
+
|
72
|
+
super(type, **options, fn: fn)
|
44
73
|
end
|
45
74
|
|
46
|
-
# @return [
|
47
|
-
|
48
|
-
|
75
|
+
# @return [Object]
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
def call_safe(input)
|
79
|
+
coerced = fn.(input) { |output = input| return yield(output) }
|
80
|
+
type.call_safe(coerced) { |output = coerced| yield(output) }
|
49
81
|
end
|
50
82
|
|
51
|
-
# @param [Object] input
|
52
83
|
# @return [Object]
|
53
|
-
|
54
|
-
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
def call_unsafe(input)
|
87
|
+
type.call_unsafe(fn.(input))
|
55
88
|
end
|
56
|
-
alias_method :[], :call
|
57
89
|
|
58
90
|
# @param [Object] input
|
59
91
|
# @param [#call,nil] block
|
92
|
+
#
|
60
93
|
# @return [Logic::Result, Types::Result]
|
61
94
|
# @return [Object] if block given and try fails
|
95
|
+
#
|
96
|
+
# @api public
|
62
97
|
def try(input, &block)
|
63
|
-
|
64
|
-
rescue
|
65
|
-
failure(input, e
|
98
|
+
value = fn.(input)
|
99
|
+
rescue CoercionError => e
|
100
|
+
failure = failure(input, e)
|
101
|
+
block_given? ? yield(failure) : failure
|
102
|
+
else
|
103
|
+
type.try(value, &block)
|
66
104
|
end
|
67
105
|
|
106
|
+
# Build a new constructor by appending a block to the coercion function
|
107
|
+
#
|
68
108
|
# @param [#call, nil] new_fn
|
69
109
|
# @param [Hash] options
|
70
110
|
# @param [#call, nil] block
|
111
|
+
#
|
71
112
|
# @return [Constructor]
|
113
|
+
#
|
114
|
+
# @api public
|
72
115
|
def constructor(new_fn = nil, **options, &block)
|
73
|
-
|
74
|
-
right = fn
|
116
|
+
next_fn = Function[new_fn || block]
|
75
117
|
|
76
|
-
|
118
|
+
if next_fn.wrapper?
|
119
|
+
self.class.wrapper_type.new(with(**options), fn: next_fn)
|
120
|
+
else
|
121
|
+
with(**options, fn: fn >> next_fn)
|
122
|
+
end
|
77
123
|
end
|
78
124
|
alias_method :append, :constructor
|
79
125
|
alias_method :>>, :constructor
|
80
126
|
|
81
|
-
# @param [Object] value
|
82
|
-
# @return [Boolean]
|
83
|
-
def valid?(value)
|
84
|
-
constructed_value = fn[value]
|
85
|
-
rescue NoMethodError, TypeError, ArgumentError
|
86
|
-
false
|
87
|
-
else
|
88
|
-
type.valid?(constructed_value)
|
89
|
-
end
|
90
|
-
alias_method :===, :valid?
|
91
|
-
|
92
127
|
# @return [Class]
|
128
|
+
#
|
129
|
+
# @api private
|
93
130
|
def constrained_type
|
94
131
|
Constrained::Coercible
|
95
132
|
end
|
96
133
|
|
97
|
-
# @api public
|
98
|
-
#
|
99
134
|
# @see Nominal#to_ast
|
135
|
+
#
|
136
|
+
# @api public
|
100
137
|
def to_ast(meta: true)
|
101
|
-
[:constructor, [type.to_ast(meta: meta),
|
102
|
-
register_fn(fn),
|
103
|
-
meta ? self.meta : EMPTY_HASH]]
|
138
|
+
[:constructor, [type.to_ast(meta: meta), fn.to_ast]]
|
104
139
|
end
|
105
140
|
|
106
|
-
#
|
141
|
+
# Build a new constructor by prepending a block to the coercion function
|
107
142
|
#
|
108
143
|
# @param [#call, nil] new_fn
|
109
144
|
# @param [Hash] options
|
110
145
|
# @param [#call, nil] block
|
146
|
+
#
|
111
147
|
# @return [Constructor]
|
148
|
+
#
|
149
|
+
# @api public
|
112
150
|
def prepend(new_fn = nil, **options, &block)
|
113
|
-
|
114
|
-
right = fn
|
115
|
-
|
116
|
-
with(**options, fn: -> input { right[left[input]] })
|
151
|
+
with(**options, fn: fn << (new_fn || block))
|
117
152
|
end
|
118
153
|
alias_method :<<, :prepend
|
119
154
|
|
120
|
-
|
155
|
+
# Build a lax type
|
156
|
+
#
|
157
|
+
# @return [Lax]
|
158
|
+
# @api public
|
159
|
+
def lax
|
160
|
+
Lax.new(constructor_type[type.lax, **options])
|
161
|
+
end
|
121
162
|
|
122
|
-
|
123
|
-
|
163
|
+
# Wrap the type with a proc
|
164
|
+
#
|
165
|
+
# @return [Proc]
|
166
|
+
#
|
167
|
+
# @api public
|
168
|
+
def to_proc
|
169
|
+
proc { |value| self.(value) }
|
124
170
|
end
|
125
171
|
|
172
|
+
private
|
173
|
+
|
126
174
|
# @param [Symbol] meth
|
127
175
|
# @param [Boolean] include_private
|
128
176
|
# @return [Boolean]
|
177
|
+
#
|
178
|
+
# @api private
|
129
179
|
def respond_to_missing?(meth, include_private = false)
|
130
180
|
super || type.respond_to?(meth)
|
131
181
|
end
|
132
182
|
|
133
183
|
# Delegates missing methods to {#type}
|
184
|
+
#
|
134
185
|
# @param [Symbol] method
|
135
186
|
# @param [Array] args
|
136
187
|
# @param [#call, nil] block
|
188
|
+
#
|
189
|
+
# @api private
|
137
190
|
def method_missing(method, *args, &block)
|
138
191
|
if type.respond_to?(method)
|
139
|
-
response = type.
|
192
|
+
response = type.public_send(method, *args, &block)
|
140
193
|
|
141
|
-
if
|
142
|
-
response.constructor_type
|
194
|
+
if response.is_a?(Type) && type.class.equal?(response.class)
|
195
|
+
response.constructor_type[response, **options]
|
143
196
|
else
|
144
197
|
response
|
145
198
|
end
|
@@ -147,10 +200,6 @@ module Dry
|
|
147
200
|
super
|
148
201
|
end
|
149
202
|
end
|
150
|
-
|
151
|
-
def composable?(value)
|
152
|
-
value.kind_of?(Builder)
|
153
|
-
end
|
154
203
|
end
|
155
204
|
end
|
156
205
|
end
|
data/lib/dry/types/container.rb
CHANGED
data/lib/dry/types/core.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types/any"
|
2
4
|
|
3
5
|
module Dry
|
4
6
|
module Types
|
5
7
|
# Primitives with {Kernel} coercion methods
|
6
|
-
|
8
|
+
KERNEL_COERCIBLE = {
|
7
9
|
string: String,
|
8
10
|
integer: Integer,
|
9
11
|
float: Float,
|
@@ -12,10 +14,19 @@ module Dry
|
|
12
14
|
hash: ::Hash
|
13
15
|
}.freeze
|
14
16
|
|
15
|
-
# Primitives
|
17
|
+
# Primitives with coercions through by convention `to_*` methods
|
18
|
+
METHOD_COERCIBLE = {
|
19
|
+
symbol: Symbol
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
# By convention methods to coerce {METHOD_COERCIBLE} primitives
|
23
|
+
METHOD_COERCIBLE_METHODS = {
|
24
|
+
symbol: :to_sym
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
# Primitives that are non-coercible
|
16
28
|
NON_COERCIBLE = {
|
17
29
|
nil: NilClass,
|
18
|
-
symbol: Symbol,
|
19
30
|
class: Class,
|
20
31
|
true: TrueClass,
|
21
32
|
false: FalseClass,
|
@@ -26,7 +37,10 @@ module Dry
|
|
26
37
|
}.freeze
|
27
38
|
|
28
39
|
# All built-in primitives
|
29
|
-
ALL_PRIMITIVES =
|
40
|
+
ALL_PRIMITIVES = [KERNEL_COERCIBLE, METHOD_COERCIBLE, NON_COERCIBLE].reduce(&:merge).freeze
|
41
|
+
|
42
|
+
# All coercible types
|
43
|
+
COERCIBLE = KERNEL_COERCIBLE.merge(METHOD_COERCIBLE).freeze
|
30
44
|
|
31
45
|
# All built-in primitives except {NilClass}
|
32
46
|
NON_NIL = ALL_PRIMITIVES.reject { |name, _| name == :nil }.freeze
|
@@ -44,14 +58,23 @@ module Dry
|
|
44
58
|
register("strict.#{name}", type)
|
45
59
|
end
|
46
60
|
|
47
|
-
# Register {
|
48
|
-
|
61
|
+
# Register {KERNEL_COERCIBLE} types
|
62
|
+
KERNEL_COERCIBLE.each do |name, primitive|
|
49
63
|
register("coercible.#{name}", self["nominal.#{name}"].constructor(Kernel.method(primitive.name)))
|
50
64
|
end
|
51
65
|
|
66
|
+
# Register {METHOD_COERCIBLE} types
|
67
|
+
METHOD_COERCIBLE.each_key do |name|
|
68
|
+
register(
|
69
|
+
"coercible.#{name}", self["nominal.#{name}"].constructor(&METHOD_COERCIBLE_METHODS[name])
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
52
73
|
# Register optional strict {NON_NIL} types
|
53
74
|
NON_NIL.each_key do |name|
|
54
|
-
|
75
|
+
type = self[name.to_s].optional
|
76
|
+
register("optional.strict.#{name}", type)
|
77
|
+
register("optional.#{name}", type)
|
55
78
|
end
|
56
79
|
|
57
80
|
# Register optional {COERCIBLE} types
|
@@ -71,6 +94,6 @@ module Dry
|
|
71
94
|
end
|
72
95
|
end
|
73
96
|
|
74
|
-
require
|
75
|
-
require
|
76
|
-
require
|
97
|
+
require "dry/types/coercions"
|
98
|
+
require "dry/types/params"
|
99
|
+
require "dry/types/json"
|
data/lib/dry/types/decorator.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/types/options"
|
2
4
|
|
3
5
|
module Dry
|
4
6
|
module Types
|
7
|
+
# Common API for types
|
8
|
+
#
|
9
|
+
# @api public
|
5
10
|
module Decorator
|
6
11
|
include Options
|
7
12
|
|
@@ -9,63 +14,76 @@ module Dry
|
|
9
14
|
attr_reader :type
|
10
15
|
|
11
16
|
# @param [Type] type
|
12
|
-
def initialize(type,
|
17
|
+
def initialize(type, *, **)
|
13
18
|
super
|
14
19
|
@type = type
|
15
20
|
end
|
16
21
|
|
17
22
|
# @param [Object] input
|
18
23
|
# @param [#call, nil] block
|
24
|
+
#
|
19
25
|
# @return [Result,Logic::Result]
|
20
26
|
# @return [Object] if block given and try fails
|
27
|
+
#
|
28
|
+
# @api public
|
21
29
|
def try(input, &block)
|
22
30
|
type.try(input, &block)
|
23
31
|
end
|
24
32
|
|
25
|
-
# @param [Object] value
|
26
|
-
# @return [Boolean]
|
27
|
-
def valid?(value)
|
28
|
-
type.valid?(value)
|
29
|
-
end
|
30
|
-
alias_method :===, :valid?
|
31
|
-
|
32
33
|
# @return [Boolean]
|
34
|
+
#
|
35
|
+
# @api public
|
33
36
|
def default?
|
34
37
|
type.default?
|
35
38
|
end
|
36
39
|
|
37
40
|
# @return [Boolean]
|
41
|
+
#
|
42
|
+
# @api public
|
38
43
|
def constrained?
|
39
44
|
type.constrained?
|
40
45
|
end
|
41
46
|
|
42
|
-
# @return [Sum]
|
43
|
-
def optional
|
44
|
-
Types['strict.nil'] | self
|
45
|
-
end
|
46
|
-
|
47
47
|
# @param [Symbol] meth
|
48
48
|
# @param [Boolean] include_private
|
49
|
+
#
|
49
50
|
# @return [Boolean]
|
51
|
+
#
|
52
|
+
# @api public
|
50
53
|
def respond_to_missing?(meth, include_private = false)
|
51
54
|
super || type.respond_to?(meth)
|
52
55
|
end
|
53
56
|
|
57
|
+
# Wrap the type with a proc
|
58
|
+
#
|
59
|
+
# @return [Proc]
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
def to_proc
|
63
|
+
proc { |value| self.(value) }
|
64
|
+
end
|
65
|
+
|
54
66
|
private
|
55
67
|
|
56
68
|
# @param [Object] response
|
69
|
+
#
|
57
70
|
# @return [Boolean]
|
71
|
+
#
|
72
|
+
# @api private
|
58
73
|
def decorate?(response)
|
59
|
-
response.
|
74
|
+
response.is_a?(type.class)
|
60
75
|
end
|
61
76
|
|
62
77
|
# Delegates missing methods to {#type}
|
78
|
+
#
|
63
79
|
# @param [Symbol] meth
|
64
80
|
# @param [Array] args
|
65
81
|
# @param [#call, nil] block
|
82
|
+
#
|
83
|
+
# @api private
|
66
84
|
def method_missing(meth, *args, &block)
|
67
85
|
if type.respond_to?(meth)
|
68
|
-
response = type.
|
86
|
+
response = type.public_send(meth, *args, &block)
|
69
87
|
|
70
88
|
if decorate?(response)
|
71
89
|
__new__(response)
|
@@ -76,10 +94,13 @@ module Dry
|
|
76
94
|
super
|
77
95
|
end
|
78
96
|
end
|
97
|
+
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
79
98
|
|
80
99
|
# Replace underlying type
|
100
|
+
#
|
101
|
+
# @api private
|
81
102
|
def __new__(type)
|
82
|
-
self.class.new(type, options)
|
103
|
+
self.class.new(type, *@__args__.drop(1), **@options)
|
83
104
|
end
|
84
105
|
end
|
85
106
|
end
|
data/lib/dry/types/default.rb
CHANGED
@@ -1,31 +1,46 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/core/equalizer"
|
4
|
+
require "dry/types/decorator"
|
2
5
|
|
3
6
|
module Dry
|
4
7
|
module Types
|
8
|
+
# Default types are useful when a missing value should be replaced by a default one
|
9
|
+
#
|
10
|
+
# @api public
|
5
11
|
class Default
|
6
|
-
|
7
|
-
include Decorator
|
8
|
-
include Builder
|
9
|
-
include Printable
|
10
|
-
include Dry::Equalizer(:type, :options, :value, inspect: false)
|
11
|
-
|
12
|
+
# @api private
|
12
13
|
class Callable < Default
|
13
|
-
include Dry::Equalizer(:type, :
|
14
|
+
include Dry::Equalizer(:type, inspect: false, immutable: true)
|
14
15
|
|
15
16
|
# Evaluates given callable
|
16
17
|
# @return [Object]
|
17
18
|
def evaluate
|
18
19
|
value.call(type)
|
19
20
|
end
|
21
|
+
|
22
|
+
# @return [true]
|
23
|
+
def callable?
|
24
|
+
true
|
25
|
+
end
|
20
26
|
end
|
21
27
|
|
28
|
+
include Type
|
29
|
+
include Decorator
|
30
|
+
include Builder
|
31
|
+
include Printable
|
32
|
+
include Dry::Equalizer(:type, :value, inspect: false, immutable: true)
|
33
|
+
|
22
34
|
# @return [Object]
|
23
35
|
attr_reader :value
|
24
36
|
|
25
37
|
alias_method :evaluate, :value
|
26
38
|
|
27
39
|
# @param [Object, #call] value
|
40
|
+
#
|
28
41
|
# @return [Class] {Default} or {Default::Callable}
|
42
|
+
#
|
43
|
+
# @api private
|
29
44
|
def self.[](value)
|
30
45
|
if value.respond_to?(:call)
|
31
46
|
Callable
|
@@ -36,48 +51,78 @@ module Dry
|
|
36
51
|
|
37
52
|
# @param [Type] type
|
38
53
|
# @param [Object] value
|
54
|
+
#
|
55
|
+
# @api private
|
39
56
|
def initialize(type, value, **options)
|
40
57
|
super
|
41
58
|
@value = value
|
42
59
|
end
|
43
60
|
|
61
|
+
# Build a constrained type
|
62
|
+
#
|
44
63
|
# @param [Array] args see {Dry::Types::Builder#constrained}
|
64
|
+
#
|
45
65
|
# @return [Default]
|
66
|
+
#
|
67
|
+
# @api public
|
46
68
|
def constrained(*args)
|
47
69
|
type.constrained(*args).default(value)
|
48
70
|
end
|
49
71
|
|
50
72
|
# @return [true]
|
73
|
+
#
|
74
|
+
# @api public
|
51
75
|
def default?
|
52
76
|
true
|
53
77
|
end
|
54
78
|
|
55
79
|
# @param [Object] input
|
80
|
+
#
|
56
81
|
# @return [Result::Success]
|
82
|
+
#
|
83
|
+
# @api public
|
57
84
|
def try(input)
|
58
85
|
success(call(input))
|
59
86
|
end
|
60
87
|
|
88
|
+
# @return [Boolean]
|
89
|
+
#
|
90
|
+
# @api public
|
61
91
|
def valid?(value = Undefined)
|
62
|
-
|
92
|
+
Undefined.equal?(value) || super
|
63
93
|
end
|
64
94
|
|
65
95
|
# @param [Object] input
|
96
|
+
#
|
66
97
|
# @return [Object] value passed through {#type} or {#default} value
|
67
|
-
|
98
|
+
#
|
99
|
+
# @api private
|
100
|
+
def call_unsafe(input = Undefined)
|
68
101
|
if input.equal?(Undefined)
|
69
102
|
evaluate
|
70
103
|
else
|
71
|
-
Undefined.default(type
|
104
|
+
Undefined.default(type.call_unsafe(input)) { evaluate }
|
72
105
|
end
|
73
106
|
end
|
74
|
-
alias_method :[], :call
|
75
107
|
|
76
|
-
|
108
|
+
# @param [Object] input
|
109
|
+
#
|
110
|
+
# @return [Object] value passed through {#type} or {#default} value
|
111
|
+
#
|
112
|
+
# @api private
|
113
|
+
def call_safe(input = Undefined, &block)
|
114
|
+
if input.equal?(Undefined)
|
115
|
+
evaluate
|
116
|
+
else
|
117
|
+
Undefined.default(type.call_safe(input, &block)) { evaluate }
|
118
|
+
end
|
119
|
+
end
|
77
120
|
|
78
|
-
#
|
79
|
-
|
80
|
-
|
121
|
+
# @return [false]
|
122
|
+
#
|
123
|
+
# @api private
|
124
|
+
def callable?
|
125
|
+
false
|
81
126
|
end
|
82
127
|
end
|
83
128
|
end
|