pangea-sdk 0.0.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.
- checksums.yaml +7 -0
- data/.ignore +2 -0
- data/README.md +1 -0
- data/lib/pangea/client.rb +51 -0
- data/lib/pangea/errors.rb +113 -0
- data/lib/pangea/internal/transport/base_client.rb +346 -0
- data/lib/pangea/internal/transport/pooled_net_requester.rb +191 -0
- data/lib/pangea/internal/type/array_of.rb +119 -0
- data/lib/pangea/internal/type/base_model.rb +289 -0
- data/lib/pangea/internal/type/boolean.rb +44 -0
- data/lib/pangea/internal/type/converter.rb +228 -0
- data/lib/pangea/internal/type/hash_of.rb +166 -0
- data/lib/pangea/internal/type/request_parameters.rb +38 -0
- data/lib/pangea/internal/type/union.rb +66 -0
- data/lib/pangea/internal/type/unknown.rb +50 -0
- data/lib/pangea/internal/util.rb +429 -0
- data/lib/pangea/internal.rb +12 -0
- data/lib/pangea/models/ai_guard/classification_result.rb +33 -0
- data/lib/pangea/models/ai_guard/hardening_result.rb +27 -0
- data/lib/pangea/models/ai_guard/language_result.rb +20 -0
- data/lib/pangea/models/ai_guard/malicious_entity_result.rb +42 -0
- data/lib/pangea/models/ai_guard/prompt_injection_result.rb +33 -0
- data/lib/pangea/models/ai_guard/redact_entity_result.rb +43 -0
- data/lib/pangea/models/ai_guard/single_entity_result.rb +21 -0
- data/lib/pangea/models/ai_guard/text_guard_message_param.rb +19 -0
- data/lib/pangea/models/ai_guard/text_guard_params.rb +24 -0
- data/lib/pangea/models/ai_guard/text_guard_result.rb +308 -0
- data/lib/pangea/models/ai_guard/topic_result.rb +33 -0
- data/lib/pangea/models/pangea_response.rb +67 -0
- data/lib/pangea/request_options.rb +35 -0
- data/lib/pangea/services/ai_guard.rb +62 -0
- data/lib/pangea/version.rb +5 -0
- data/lib/pangea.rb +45 -0
- data/manifest.yaml +6 -0
- data/rbi/lib/pangea/client.rbi +25 -0
- data/rbi/lib/pangea/internal/internal.rbi +28 -0
- data/rbi/lib/pangea/internal/transport/base_client.rbi +18 -0
- data/rbi/lib/pangea/internal/type/array_of.rbi +66 -0
- data/rbi/lib/pangea/internal/type/base_model.rbi +33 -0
- data/rbi/lib/pangea/internal/type/boolean.rbi +46 -0
- data/rbi/lib/pangea/internal/type/converter.rbi +38 -0
- data/rbi/lib/pangea/internal/type/request_parameters.rbi +20 -0
- data/rbi/lib/pangea/internal/type/union.rbi +21 -0
- data/rbi/lib/pangea/internal/type/unknown.rbi +20 -0
- data/rbi/lib/pangea/internal.rbi +7 -0
- data/rbi/lib/pangea/models/ai_guard/text_guard_message_param.rbi +15 -0
- data/rbi/lib/pangea/models/ai_guard/text_guard_result.rbi +13 -0
- data/rbi/lib/pangea/models/pangea_response.rbi +31 -0
- data/rbi/lib/pangea/request_options.rbi +17 -0
- data/rbi/lib/pangea/services/ai_guard.rbi +28 -0
- data/rbi/lib/pangea/version.rbi +5 -0
- data/sig/pangea/client.rbs +12 -0
- data/sig/pangea/internal/transport/base_client.rbs +14 -0
- data/sig/pangea/internal/type/base_model.rbs +12 -0
- data/sig/pangea/internal/type/boolean.rbs +10 -0
- data/sig/pangea/internal/type/converter.rbs +9 -0
- data/sig/pangea/internal/type/request_parameters.rbs +15 -0
- data/sig/pangea/models/pangea_response.rbs +12 -0
- data/sig/pangea/models/text_guard_result.rbs +19 -0
- data/sig/pangea/request_options.rbs +34 -0
- data/sig/pangea/services/ai_guard.rbs +12 -0
- data/sig/pangea/version.rbs +3 -0
- metadata +126 -0
@@ -0,0 +1,228 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pangea
|
4
|
+
module Internal
|
5
|
+
module Type
|
6
|
+
module Converter
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
# @param value [Object]
|
10
|
+
#
|
11
|
+
# @param state [Hash{Symbol=>Object}] .
|
12
|
+
#
|
13
|
+
# @option state [Boolean, :strong] :strictness
|
14
|
+
#
|
15
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
16
|
+
#
|
17
|
+
# @option state [Integer] :branched
|
18
|
+
#
|
19
|
+
# @return [Object]
|
20
|
+
def coerce(value, state:) = (raise NotImplementedError)
|
21
|
+
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
# @param value [Object]
|
25
|
+
#
|
26
|
+
# @param state [Hash{Symbol=>Object}] .
|
27
|
+
#
|
28
|
+
# @option state [Boolean] :can_retry
|
29
|
+
#
|
30
|
+
# @return [Object]
|
31
|
+
def dump(value, state:)
|
32
|
+
case value
|
33
|
+
in Array
|
34
|
+
value.map { Pangea::Internal::Type::Unknown.dump(_1, state: state) }
|
35
|
+
in Hash
|
36
|
+
value.transform_values { Pangea::Internal::Type::Unknown.dump(_1, state: state) }
|
37
|
+
in Pangea::Internal::Type::BaseModel
|
38
|
+
value.class.dump(value, state: state)
|
39
|
+
in StringIO
|
40
|
+
value.string
|
41
|
+
in Pathname | IO
|
42
|
+
state[:can_retry] = false if value.is_a?(IO)
|
43
|
+
Pangea::Internal::Util::SerializationAdapter.new(value)
|
44
|
+
else
|
45
|
+
value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
# Based on `target`, transform `value` into `target`, to the extent possible:
|
53
|
+
#
|
54
|
+
# 1. if the given `value` conforms to `target` already, return the given `value`
|
55
|
+
# 2. if it's possible and safe to convert the given `value` to `target`, then the
|
56
|
+
# converted value
|
57
|
+
# 3. otherwise, the given `value` unaltered
|
58
|
+
#
|
59
|
+
# @param target [Pangea::Internal::Type::Converter, Class]
|
60
|
+
#
|
61
|
+
# @param value [Object]
|
62
|
+
#
|
63
|
+
# @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false`, or `:strong`. This informs the
|
64
|
+
# coercion strategy when we have to decide between multiple possible conversion
|
65
|
+
# targets:
|
66
|
+
#
|
67
|
+
# - `true`: the conversion must be exact, with minimum coercion.
|
68
|
+
# - `false`: the conversion can be approximate, with some coercion.
|
69
|
+
# - `:strong`: the conversion must be exact, with no coercion, and raise an error
|
70
|
+
# if not possible.
|
71
|
+
#
|
72
|
+
# The `exactness` is `Hash` with keys being one of `yes`, `no`, or `maybe`. For
|
73
|
+
# any given conversion attempt, the exactness will be updated based on how closely
|
74
|
+
# the value recursively matches the target type:
|
75
|
+
#
|
76
|
+
# - `yes`: the value can be converted to the target type with minimum coercion.
|
77
|
+
# - `maybe`: the value can be converted to the target type with some reasonable
|
78
|
+
# coercion.
|
79
|
+
# - `no`: the value cannot be converted to the target type.
|
80
|
+
#
|
81
|
+
# See implementation below for more details.
|
82
|
+
#
|
83
|
+
# @option state [Boolean, :strong] :strictness
|
84
|
+
#
|
85
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
86
|
+
#
|
87
|
+
# @option state [Integer] :branched
|
88
|
+
#
|
89
|
+
# @return [Object]
|
90
|
+
def coerce(
|
91
|
+
target,
|
92
|
+
value,
|
93
|
+
state: {strictness: true, exactness: {yes: 0, no: 0, maybe: 0}, branched: 0}
|
94
|
+
)
|
95
|
+
# rubocop:disable Lint/SuppressedException
|
96
|
+
# rubocop:disable Metrics/BlockNesting
|
97
|
+
|
98
|
+
strictness, exactness = state.fetch_values(:strictness, :exactness)
|
99
|
+
|
100
|
+
case target
|
101
|
+
in Pangea::Internal::Type::Converter
|
102
|
+
return target.coerce(value, state: state)
|
103
|
+
in Class
|
104
|
+
if value.is_a?(target)
|
105
|
+
exactness[:yes] += 1
|
106
|
+
return value
|
107
|
+
end
|
108
|
+
|
109
|
+
case target
|
110
|
+
in -> { _1 <= NilClass }
|
111
|
+
exactness[value.nil? ? :yes : :maybe] += 1
|
112
|
+
return nil
|
113
|
+
in -> { _1 <= Integer }
|
114
|
+
if value.is_a?(Integer)
|
115
|
+
exactness[:yes] += 1
|
116
|
+
return value
|
117
|
+
elsif strictness == :strong && Integer(value, exception: false) != value
|
118
|
+
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
119
|
+
raise value.is_a?(Numeric) ? ArgumentError.new(message) : TypeError.new(message)
|
120
|
+
else
|
121
|
+
Kernel.then do
|
122
|
+
return Integer(value).tap { exactness[:maybe] += 1 }
|
123
|
+
rescue ArgumentError, TypeError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
in -> { _1 <= Float }
|
127
|
+
if value.is_a?(Numeric)
|
128
|
+
exactness[:yes] += 1
|
129
|
+
return Float(value)
|
130
|
+
elsif strictness == :strong
|
131
|
+
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
132
|
+
raise TypeError.new(message)
|
133
|
+
else
|
134
|
+
Kernel.then do
|
135
|
+
return Float(value).tap { exactness[:maybe] += 1 }
|
136
|
+
rescue ArgumentError, TypeError
|
137
|
+
end
|
138
|
+
end
|
139
|
+
in -> { _1 <= String }
|
140
|
+
case value
|
141
|
+
in String | Symbol | Numeric
|
142
|
+
exactness[value.is_a?(Numeric) ? :maybe : :yes] += 1
|
143
|
+
return value.to_s
|
144
|
+
in StringIO
|
145
|
+
exactness[:yes] += 1
|
146
|
+
return value.string
|
147
|
+
else
|
148
|
+
if strictness == :strong
|
149
|
+
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
150
|
+
raise TypeError.new(message)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
in -> { _1 <= Date || _1 <= Time }
|
154
|
+
Kernel.then do
|
155
|
+
return target.parse(value).tap { exactness[:yes] += 1 }
|
156
|
+
rescue ArgumentError, TypeError => e
|
157
|
+
raise e if strictness == :strong
|
158
|
+
end
|
159
|
+
in -> { _1 <= StringIO } if value.is_a?(String)
|
160
|
+
exactness[:yes] += 1
|
161
|
+
return StringIO.new(value.b)
|
162
|
+
else
|
163
|
+
end
|
164
|
+
in Symbol
|
165
|
+
case value
|
166
|
+
in Symbol | String
|
167
|
+
if value.to_sym == target
|
168
|
+
exactness[:yes] += 1
|
169
|
+
return target
|
170
|
+
else
|
171
|
+
exactness[:maybe] += 1
|
172
|
+
return value
|
173
|
+
end
|
174
|
+
else
|
175
|
+
if strictness == :strong
|
176
|
+
message = "cannot convert non-matching #{value.class} into #{target.inspect}"
|
177
|
+
raise ArgumentError.new(message)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
else
|
181
|
+
end
|
182
|
+
|
183
|
+
exactness[:no] += 1
|
184
|
+
value
|
185
|
+
|
186
|
+
# rubocop:enable Metrics/BlockNesting
|
187
|
+
# rubocop:enable Lint/SuppressedException
|
188
|
+
end
|
189
|
+
|
190
|
+
# @api private
|
191
|
+
#
|
192
|
+
# @param target [Pangea::Internal::Type::Converter, Class]
|
193
|
+
#
|
194
|
+
# @param value [Object]
|
195
|
+
#
|
196
|
+
# @param state [Hash{Symbol=>Object}] .
|
197
|
+
#
|
198
|
+
# @option state [Boolean] :can_retry
|
199
|
+
#
|
200
|
+
# @return [Object]
|
201
|
+
def dump(target, value, state: {can_retry: true})
|
202
|
+
case target
|
203
|
+
in Pangea::Internal::Type::Converter
|
204
|
+
target.dump(value, state: state)
|
205
|
+
else
|
206
|
+
Pangea::Internal::Type::Unknown.dump(value, state: state)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def type_info(spec)
|
211
|
+
case spec
|
212
|
+
in Proc
|
213
|
+
spec
|
214
|
+
in Hash
|
215
|
+
type_info(spec.slice(:const, :enum, :union).first&.last)
|
216
|
+
in true | false
|
217
|
+
-> { Pangea::Internal::Type::Boolean }
|
218
|
+
in Pangea::Internal::Type::Converter | Class | Symbol
|
219
|
+
-> { spec }
|
220
|
+
in NilClass | Integer | Float
|
221
|
+
-> { spec.class }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pangea
|
4
|
+
module Internal
|
5
|
+
module Type
|
6
|
+
# @api private
|
7
|
+
#
|
8
|
+
# @abstract
|
9
|
+
#
|
10
|
+
# @generic Elem
|
11
|
+
#
|
12
|
+
# Hash of items of a given type.
|
13
|
+
class HashOf
|
14
|
+
include Pangea::Internal::Type::Converter
|
15
|
+
|
16
|
+
private_class_method :new
|
17
|
+
|
18
|
+
# @overload [](type_info, spec = {})
|
19
|
+
#
|
20
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class]
|
21
|
+
#
|
22
|
+
# @param spec [Hash{Symbol=>Object}] .
|
23
|
+
#
|
24
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
25
|
+
#
|
26
|
+
# @option spec [Proc] :enum
|
27
|
+
#
|
28
|
+
# @option spec [Proc] :union
|
29
|
+
#
|
30
|
+
# @option spec [Boolean] :"nil?"
|
31
|
+
def self.[](...) = new(...)
|
32
|
+
|
33
|
+
# @param other [Object]
|
34
|
+
#
|
35
|
+
# @return [Boolean]
|
36
|
+
def ===(other)
|
37
|
+
type = item_type
|
38
|
+
case other
|
39
|
+
in Hash
|
40
|
+
other.all? do |key, val|
|
41
|
+
case [key, val]
|
42
|
+
in [Symbol | String, ^type]
|
43
|
+
true
|
44
|
+
else
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
else
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param other [Object]
|
54
|
+
#
|
55
|
+
# @return [Boolean]
|
56
|
+
def ==(other)
|
57
|
+
# rubocop:disable Layout/LineLength
|
58
|
+
other.is_a?(Pangea::Internal::Type::HashOf) && other.nilable? == nilable? && other.item_type == item_type
|
59
|
+
# rubocop:enable Layout/LineLength
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Integer]
|
63
|
+
def hash = [self.class, item_type].hash
|
64
|
+
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
# @param value [Hash{Object=>Object}, Object]
|
68
|
+
#
|
69
|
+
# @param state [Hash{Symbol=>Object}] .
|
70
|
+
#
|
71
|
+
# @option state [Boolean, :strong] :strictness
|
72
|
+
#
|
73
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
74
|
+
#
|
75
|
+
# @option state [Integer] :branched
|
76
|
+
#
|
77
|
+
# @return [Hash{Symbol=>Object}, Object]
|
78
|
+
def coerce(value, state:)
|
79
|
+
exactness = state.fetch(:exactness)
|
80
|
+
|
81
|
+
unless value.is_a?(Hash)
|
82
|
+
exactness[:no] += 1
|
83
|
+
return value
|
84
|
+
end
|
85
|
+
|
86
|
+
target = item_type
|
87
|
+
exactness[:yes] += 1
|
88
|
+
value
|
89
|
+
.to_h do |key, val|
|
90
|
+
k = key.is_a?(String) ? key.to_sym : key
|
91
|
+
v =
|
92
|
+
case [nilable?, val]
|
93
|
+
in [true, nil]
|
94
|
+
exactness[:yes] += 1
|
95
|
+
nil
|
96
|
+
else
|
97
|
+
Pangea::Internal::Type::Converter.coerce(target, val, state: state)
|
98
|
+
end
|
99
|
+
|
100
|
+
exactness[:no] += 1 unless k.is_a?(Symbol)
|
101
|
+
[k, v]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# @api private
|
106
|
+
#
|
107
|
+
# @param value [Hash{Object=>Object}, Object]
|
108
|
+
#
|
109
|
+
# @param state [Hash{Symbol=>Object}] .
|
110
|
+
#
|
111
|
+
# @option state [Boolean] :can_retry
|
112
|
+
#
|
113
|
+
# @return [Hash{Symbol=>Object}, Object]
|
114
|
+
def dump(value, state:)
|
115
|
+
target = item_type
|
116
|
+
if value.is_a?(Hash)
|
117
|
+
value.transform_values do
|
118
|
+
Pangea::Internal::Type::Converter.dump(target, _1, state: state)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
super
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# @api private
|
126
|
+
#
|
127
|
+
# @return [generic<Elem>]
|
128
|
+
protected def item_type = @item_type_fn.call
|
129
|
+
|
130
|
+
# @api private
|
131
|
+
#
|
132
|
+
# @return [Boolean]
|
133
|
+
protected def nilable? = @nilable
|
134
|
+
|
135
|
+
# @api private
|
136
|
+
#
|
137
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class]
|
138
|
+
#
|
139
|
+
# @param spec [Hash{Symbol=>Object}] .
|
140
|
+
#
|
141
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
142
|
+
#
|
143
|
+
# @option spec [Proc] :enum
|
144
|
+
#
|
145
|
+
# @option spec [Proc] :union
|
146
|
+
#
|
147
|
+
# @option spec [Boolean] :"nil?"
|
148
|
+
def initialize(type_info, spec = {})
|
149
|
+
@item_type_fn = Pangea::Internal::Type::Converter.type_info(type_info || spec)
|
150
|
+
@nilable = spec.fetch(:nil?, false)
|
151
|
+
end
|
152
|
+
|
153
|
+
# @api private
|
154
|
+
#
|
155
|
+
# @param depth [Integer]
|
156
|
+
#
|
157
|
+
# @return [String]
|
158
|
+
def inspect(depth: 0)
|
159
|
+
items = Pangea::Internal::Type::Converter.inspect(item_type, depth: depth.succ)
|
160
|
+
|
161
|
+
"#{self.class}[#{[items, nilable? ? 'nil' : nil].compact.join(' | ')}]"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pangea
|
4
|
+
module Internal
|
5
|
+
module Type
|
6
|
+
# @api private
|
7
|
+
module RequestParameters
|
8
|
+
def self.included(mod)
|
9
|
+
raise ArgumentError.new(mod) unless mod <= Pangea::Internal::Type::BaseModel
|
10
|
+
|
11
|
+
mod.optional(:request_options, Pangea::RequestOptions)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
module Converter
|
16
|
+
# @api private
|
17
|
+
def dump_request(params)
|
18
|
+
state = {can_retry: true}
|
19
|
+
case (dumped = dump(params, state: state))
|
20
|
+
in Hash
|
21
|
+
options = Pangea::Internal::Util.coerce_hash(dumped[:request_options])
|
22
|
+
request_options =
|
23
|
+
case [options, state.fetch(:can_retry)]
|
24
|
+
in [Hash | nil, false]
|
25
|
+
{**options.to_h, max_retries: 0}
|
26
|
+
else
|
27
|
+
options
|
28
|
+
end
|
29
|
+
[dumped.except(:request_options), request_options]
|
30
|
+
else
|
31
|
+
[dumped, nil]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pangea
|
4
|
+
module Internal
|
5
|
+
module Type
|
6
|
+
# @api private
|
7
|
+
module Union
|
8
|
+
include Pangea::Internal::Type::Converter
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
#
|
12
|
+
# All of the specified variant info for this union.
|
13
|
+
#
|
14
|
+
# @return [Array<Array(Symbol, Proc)>]
|
15
|
+
private def known_variants = (@known_variants ||= [])
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
# @param key [Symbol, Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class]
|
20
|
+
#
|
21
|
+
# @param spec [Hash{Symbol=>Object}, Proc, Pangea::Internal::Type::Converter, Class] .
|
22
|
+
#
|
23
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
24
|
+
#
|
25
|
+
# @option spec [Proc] :enum
|
26
|
+
#
|
27
|
+
# @option spec [Proc] :union
|
28
|
+
#
|
29
|
+
# @option spec [Boolean] :"nil?"
|
30
|
+
private def variant(key, spec = nil)
|
31
|
+
variant_info =
|
32
|
+
case key
|
33
|
+
in Symbol
|
34
|
+
[key, Pangea::Internal::Type::Converter.type_info(spec)]
|
35
|
+
in Proc | Pangea::Internal::Type::Converter | Class | Hash
|
36
|
+
[nil, Pangea::Internal::Type::Converter.type_info(key)]
|
37
|
+
end
|
38
|
+
|
39
|
+
known_variants << variant_info
|
40
|
+
end
|
41
|
+
|
42
|
+
# @api private
|
43
|
+
#
|
44
|
+
# @param value [Object]
|
45
|
+
#
|
46
|
+
# @param state [Hash{Symbol=>Object}] .
|
47
|
+
#
|
48
|
+
# @option state [Boolean] :can_retry
|
49
|
+
#
|
50
|
+
# @return [Object]
|
51
|
+
def dump(value, state:)
|
52
|
+
if (target = resolve_variant(value))
|
53
|
+
return Pangea::Internal::Type::Converter.dump(target, value, state: state)
|
54
|
+
end
|
55
|
+
|
56
|
+
known_variants.each do
|
57
|
+
target = _2.call
|
58
|
+
return Pangea::Internal::Type::Converter.dump(target, value, state: state) if target === value
|
59
|
+
end
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pangea
|
4
|
+
module Internal
|
5
|
+
module Type
|
6
|
+
# @api private
|
7
|
+
#
|
8
|
+
# @abstract
|
9
|
+
class Unknown
|
10
|
+
extend Pangea::Internal::Type::Converter
|
11
|
+
|
12
|
+
private_class_method :new
|
13
|
+
|
14
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
15
|
+
|
16
|
+
# @param other [Object]
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
19
|
+
def self.===(other) = true
|
20
|
+
|
21
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
22
|
+
|
23
|
+
# @param other [Object]
|
24
|
+
#
|
25
|
+
# @return [Boolean]
|
26
|
+
def self.==(other) = other.is_a?(Class) && other <= Pangea::Internal::Type::Unknown
|
27
|
+
|
28
|
+
class << self
|
29
|
+
# @api private
|
30
|
+
#
|
31
|
+
# @param value [Object]
|
32
|
+
#
|
33
|
+
# @param state [Hash{Symbol=>Object}] .
|
34
|
+
#
|
35
|
+
# @option state [Boolean, :strong] :strictness
|
36
|
+
#
|
37
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
38
|
+
#
|
39
|
+
# @option state [Integer] :branched
|
40
|
+
#
|
41
|
+
# @return [Object]
|
42
|
+
def coerce(value, state:)
|
43
|
+
state.fetch(:exactness)[:yes] += 1
|
44
|
+
value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|