Module: Selenium::WebDriver::BiDi::Serialization::Record::Deserializer Private
| Relationships & Source Files | |
| Defined in: | rb/lib/selenium/webdriver/bidi/serialization/record.rb |
Overview
Inbound construction: the keyword #new (validated) and the wire #from_json.
Constant Summary
-
PRIMITIVE_TYPES =
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 179
Ruby classes a checkable primitive admits.
numberis any Numeric (JSON has one number type);integerrequires an Integer — a browser emits5, not5.0, for an integer (JS has no int/float split), so this rarely false-positives yet still rejects a genuine non-integer like 1.5. A field with no primitive descriptor is left unchecked.{ 'string' => [::String], 'boolean' => [::TrueClass, ::FalseClass], 'number' => [::Numeric], 'integer' => [::Integer] }.freeze
Instance Method Summary
-
#from_json(json_payload)
Internal use only
Inbound: builds from the wire.
- #new(**kwargs) Internal use only
-
#check_outbound_shape(field, value)
private
Internal use only
Outbound mirror of check_shape: a list-typed arg must be an array, a scalar-shaped one (enum or ref, not a list) must not — a local ArgumentError, not a wire round-trip.
- #check_primitive(field, raw) private Internal use only
-
#check_shape(field, raw)
private
Internal use only
A declared list must arrive as an array; a scalar-shaped field (enum or ref, not a list) must not.
- #enum_hash(field) private Internal use only
- #extra(json_payload) private Internal use only
- #fixed?(field) ⇒ Boolean private Internal use only
- #read(field, raw) private Internal use only
-
#read_list(field, raw, klass)
private
Internal use only
Parses each element.
-
#read_map_entry(field, element, klass)
private
Internal use only
A map entry is a
[key, value]pair. -
#read_ref(field, raw)
private
Internal use only
Reads a ref-typed value into its class.
-
#scalar_value(field, value)
private
Internal use only
A bare scalar at a scalar-tolerant union position must match one of the union's scalar-arm primitives (
scalaris a primitive name or an array of them); a wrong-typed scalar (a number where a string is expected) is a wire error, not something to pass through. -
#validate_values(attributes)
private
Internal use only
Checks each field's value: a required field cannot be omitted (UNSET), a non-nullable field cannot be nil (nil is neither a value nor the UNSET omit-sentinel, so it would be silently dropped on the wire), and an enum field must be in its allowed set.
- #wire_value(field, json_payload) private Internal use only
Instance Method Details
#check_outbound_shape(field, value) (private)
Outbound mirror of check_shape: a list-typed arg must be an array, a scalar-shaped one (enum or ref, not a list) must not — a local ArgumentError, not a wire round-trip.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 117
def check_outbound_shape(field, value) return if field.list == value.is_a?(::Array) return unless field.list || field.enum || field.ref kind = field.list ? 'a list' : 'a single value' raise ::ArgumentError, "#{name}##{field.name} expected #{kind}, got #{value.inspect}" end
#check_primitive(field, raw) (private)
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 184
def check_primitive(field, raw) expected = PRIMITIVE_TYPES[field.primitive] return if expected.nil? || expected.any? { |type| raw.is_a?(type) } raise Error::WebDriverError, "#{name}##{field.name} expected #{field.primitive}, got #{raw.inspect}" end
#check_shape(field, raw) (private)
A declared list must arrive as an array; a scalar-shaped field (enum or ref, not a list) must not. An opaque field carries no shape descriptor, so it passes through.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 167
def check_shape(field, raw) return if field.list == raw.is_a?(::Array) return unless field.list || field.enum || field.ref raise Error::WebDriverError, "#{name}##{field.name} expected #{field.list ? 'a list' : 'a single value'}, got #{raw.inspect}" end
#enum_hash(field) (private)
[ GitHub ]#extra(json_payload) (private)
[ GitHub ]# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 239
def extra(json_payload) known = (@wire_keys ||= fields.map(&:wire_key)) json_payload.except(*known) end
#fixed?(field) ⇒ Boolean (private)
#from_json(json_payload)
Inbound: builds from the wire. A missing required field raises (in #wire_value), enum tokens are mapped back to symbols and an unrecognized one raises (in #read), and extra keys are captured (extensible) or ignored (closed) — strict on shape, lenient on extras.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 84
def from_json(json_payload) unless json_payload.is_a?(::Hash) raise Error::WebDriverError, "#{name} expected an object on the wire, got #{json_payload.inspect}" end attributes = fields.to_h do |f| [f.name, wire_value(f, json_payload)] end attributes[:extensions] = extra(json_payload) if extensible? construct(**attributes) end
#new(**kwargs)
[ GitHub ]# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 71
def new(**kwargs) # Start from what was passed so ::Data's constructor rejects an unknown key, then fill # each field with its value or UNSET (omitted), forcing fixed discriminators. attributes = kwargs.dup fields.each { |f| attributes[f.name] = fixed?(f) ? f.fixed : attributes.fetch(f.name, UNSET) } attributes[:extensions] = kwargs.fetch(:extensions, {}) if extensible? validate_values(attributes) construct(**attributes) end
#read(field, raw) (private)
[ GitHub ]# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 137
def read(field, raw) if raw.nil? return raw if field.nullable raise Error::WebDriverError, "#{name}##{field.name} received null but is not nullable" end check_shape(field, raw) return Serialization.to_symbol("#{name}##{field.name}", raw, enum_hash(field)) if field.enum if field.ref.nil? check_primitive(field, raw) unless field.list return raw end read_ref(field, raw) end
#read_list(field, raw, klass) (private)
Parses each element. A scalar field is a map encoded as [key, value] pairs, so
every element must be a 2-item pair — each is read as one, and a malformed entry is
rejected. Non-scalar lists recurse into nested lists; other elements deserialize.
#read_map_entry(field, element, klass) (private)
A map entry is a [key, value] pair. The key is Ref / text — an object key
deserializes, a bare-string key passes through once validated against the arm's
primitive. The value is the object-only Ref and always deserializes, so a bare scalar
there is rejected (object_only holds at the value position). A non-pair element is a
malformed entry and is rejected outright.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 215
def read_map_entry(field, element, klass) unless element.is_a?(::Array) && element.size == 2 raise Error::WebDriverError, "#{name}##{field.name} expected a [key, value] pair, got #{element.inspect}" end key, value = element key = key.is_a?(::Hash) ? klass.from_json(key) : scalar_value(field, key) [key, klass.from_json(value)] end
#read_ref(field, raw) (private)
Reads a ref-typed value into its class. A scalar position is an inline union with
a scalar arm collapsed onto its union ref (a map's string keys): a non-object leaf
passes through instead of being handed to the object_only union, but only when it
matches the arm's primitive (scalar carries it). A list recurses per element.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 158
def read_ref(field, raw) klass = (@refs ||= {})[field.name] ||= Protocol.const_get(field.ref) return read_list(field, raw, klass) if field.list field.scalar && !raw.is_a?(::Hash) ? scalar_value(field, raw) : klass.from_json(raw) end
#scalar_value(field, value) (private)
A bare scalar at a scalar-tolerant union position must match one of the union's
scalar-arm primitives (scalar is a primitive name or an array of them); a
wrong-typed scalar (a number where a string is expected) is a wire error, not
something to pass through. An unrecognized primitive (none in PRIMITIVE_TYPES) is
left unchecked, matching the lenient default elsewhere.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 231
def scalar_value(field, value) expected = Array(field.scalar).flat_map { |primitive| PRIMITIVE_TYPES[primitive] || [] } return value if expected.empty? || expected.any? { |type| value.is_a?(type) } raise Error::WebDriverError, "#{name}##{field.name} expected #{Array(field.scalar).join(' or ')}, got #{value.inspect}" end
#validate_values(attributes) (private)
Checks each field's value: a required field cannot be omitted (UNSET), a non-nullable
field cannot be nil (nil is neither a value nor the UNSET omit-sentinel, so it would be
silently dropped on the wire), and an enum field must be in its allowed set. The enum
constant is resolved lazily so a cross-domain enum need not be loaded first. Outbound
only (from #new); inbound presence/enum are checked separately in wire_value+/+read.
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 103
def validate_values(attributes) fields.each do |f| value = attributes[f.name] raise ::ArgumentError, "#{name}##{f.name} is required" if UNSET.equal?(value) && f.required raise ::ArgumentError, "#{name}##{f.name} cannot be nil" if value.nil? && !f.nullable next if value.nil? || UNSET.equal?(value) check_outbound_shape(f, value) Serialization.validate!("#{name}##{f.name}", value, Protocol.const_get(f.enum)) if f.enum end end
#wire_value(field, json_payload) (private)
# File 'rb/lib/selenium/webdriver/bidi/serialization/record.rb', line 129
def wire_value(field, json_payload) return field.fixed if fixed?(field) return read(field, json_payload[field.wire_key]) if json_payload.key?(field.wire_key) return UNSET unless field.required raise Error::WebDriverError, "#{name}##{field.name} is required but was missing from the response" end