module Selenium::WebDriver::BiDi::Serialization::Record::Deserializer

def check_outbound_shape(field, value)

(enum or ref, not a list) must not — a local ArgumentError, not a wire round-trip.
Outbound mirror of check_shape: a list-typed arg must be an array, a scalar-shaped one
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

def check_primitive(field, raw)

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

def check_shape(field, raw)

list) must not. An opaque field carries no shape descriptor, so it passes through.
A declared list must arrive as an array; a scalar-shaped field (enum or ref, not a
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

def enum_hash(field)

def enum_hash(field)
  (@enums ||= {})[field.name] ||= Protocol.const_get(field.enum)
end

def extra(json_payload)

def extra(json_payload)
  known = (@wire_keys ||= fields.map(&:wire_key))
  json_payload.except(*known)
end

def fixed?(field)

def fixed?(field)
  !UNSET.equal?(field.fixed)
end

def from_json(json_payload)

extra keys are captured (extensible) or ignored (closed) — strict on shape, lenient on extras.
enum tokens are mapped back to symbols and an unrecognized one raises (in +read+), and
Inbound: builds from the wire. A missing required field raises (in +wire_value+),
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

def new(**kwargs)

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

def read(field, raw)

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
  klass = (@refs ||= {})[field.name] ||= Protocol.const_get(field.ref)
  field.list ? read_list(raw, klass) : klass.from_json(raw)
end

def read_list(raw, klass)

so their entries become typed too.
Parses each element, recursing into nested lists (e.g. a map's [key, value] pairs)
def read_list(raw, klass)
  raw.map { |element| element.is_a?(::Array) ? read_list(element, klass) : klass.from_json(element) }
end

def validate_values(attributes)

only (from +new+); inbound presence/enum are checked separately in +wire_value+/+read+.
constant is resolved lazily so a cross-domain enum need not be loaded first. Outbound
silently dropped on the wire), and an enum field must be in its allowed set. The enum
field cannot be nil (nil is neither a value nor the UNSET omit-sentinel, so it would be
Checks each field's value: a required field cannot be omitted (UNSET), a non-nullable
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

def wire_value(field, json_payload)

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