123456789_123456789_123456789_123456789_123456789_

Class: Selenium::WebDriver::BiDi::Serialization::Union Private

Overview

Resolves a wire payload to the right Data variant: a shared discriminator gives table dispatch; presence rules and a no-tag fallback cover unions without one. Subclassed (never instantiated) — each union holds its own dispatch table.

class Locator < Serialization::Union
discriminator 'type'
variants('css' => 'BrowsingContext::CssLocator')
end

Class Method Summary

  • .build(**kwargs) Internal use only

    Outbound mirror of from_json: build the variant the command's kwargs describe so its typed as_json drives null-vs-absent per field (a flat hash through ::Selenium::WebDriver::BiDi::Transport cannot).

  • .discriminator(wire_key, values = {}) Internal use only

    values maps each variant's discriminator symbol to its wire token, so an inbound payload tag (a wire string) can be matched to the symbol-keyed table.

  • .fallback(path) Internal use only
  • .from_json(json_payload) Internal use only

    A non-Hash payload is a bare scalar arm (e.g.

  • .object_only Internal use only

    Declared (via the schema's objectOnly signal) on a union whose every arm is an object, so a non-Hash payload is a schema violation rather than a scalar arm.

  • .presence(rules) Internal use only
  • .scalar_values(*values) Internal use only

    Declared (via the schema's scalarValues signal) on a non-object_only union whose bare-scalar arms are a fixed set of literals (input.Origin's "viewport" / "pointer").

  • .valid_outbound?(value) ⇒ Boolean Internal use only

    Outbound mirror of from_json: is value one this union accepts? Any variant is accepted, and a variant that is itself a union recurses (e.g. LocalValue's RemoteReference fallback).

  • .variants(table) Internal use only
  • .outbound_variant(kwargs) private Internal use only

    An explicit nil kwarg still counts as supplied; a non-nullable field set to nil is rejected at construction (Data.new), not here.

  • .payload_tag(json_payload) private Internal use only

    The wire tag mapped back to its variant symbol (the table's key); an unrecognized tag falls through as-is so select misses and from_json raises.

  • .scalar_arm?(value) ⇒ Boolean private Internal use only

    A bare-scalar arm must be one of the literals the schema pinned for this union (scalar_values, e.g. input.Origin's "viewport" / "pointer").

  • .select(json_payload) private Internal use only

    The discriminator value may legitimately be null (e.g.

  • .variant_accepts?(ref, value) ⇒ Boolean private Internal use only

    A variant that is itself a union recurses; a record variant is matched by instance.

  • .variant_for(tag, &supplied) private Internal use only

    The matching variant's ref, or nil when none matches (the fallback if declared).

  • .variant_refs private Internal use only

    Every variant's class name: the discriminated table, the presence paths, and the fallback.

Class Method Details

.build(**kwargs)

Outbound mirror of from_json: build the variant the command's kwargs describe so its typed as_json drives null-vs-absent per field (a flat hash through ::Selenium::WebDriver::BiDi::Transport cannot). Dispatch keys are wire names equal to their ruby kwarg (asserted at generation), so they match the kwargs by symbol. A mismatch here is a caller error (unlike an unknown inbound value), so it fails loudly.

Raises:

  • (::ArgumentError)
[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 79

def build(**kwargs)
  variant = outbound_variant(kwargs) ||
            raise(::ArgumentError, "no #{name} variant matches #{kwargs.inspect}")
  klass = Protocol.const_get(variant)
  # An omitted optional arrives as UNSET; forward only what was provided. A provided
  # key that isn't a field of the chosen variant is an invalid combination for this union.
  provided = kwargs.reject { |_, value| UNSET.equal?(value) }
  invalid = provided.keys - klass.fields.map(&:name)
  return klass.new(**provided) if invalid.empty?

  raise ::ArgumentError, "invalid combination for #{name}: #{invalid.join(', ')}"
end

.discriminator(wire_key, values = {})

values maps each variant's discriminator symbol to its wire token, so an inbound payload tag (a wire string) can be matched to the symbol-keyed table.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 38

def discriminator(wire_key, values = {})
  @discriminator = wire_key
  @discriminator_values = values
end

.fallback(path)

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 45

def fallback(path) = @fallback = path

.from_json(json_payload)

A non-Hash payload is a bare scalar arm (e.g. input.Origin's "viewport") with no object to dispatch on, so it is returned unchanged — unless every arm is an object (object_only), where a non-Hash cannot match any variant and is a wire error.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 59

def from_json(json_payload)
  unless json_payload.is_a?(::Hash)
    return json_payload unless @object_only

    raise Error::SerializationError, "#{name} expected an object on the wire, got #{json_payload.inspect}"
  end

  variant = select(json_payload)
  unless variant
    raise Error::SerializationError,
          "#{name} received a variant not in this Selenium's BiDi schema: #{json_payload.inspect}"
  end
  Protocol.const_get(variant).from_json(json_payload)
end

.object_only

Declared (via the schema's objectOnly signal) on a union whose every arm is an object, so a non-Hash payload is a schema violation rather than a scalar arm.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 49

def object_only = @object_only = true

.outbound_variant(kwargs) (private)

An explicit nil kwarg still counts as supplied; a non-nullable field set to nil is rejected at construction (Data.new), not here.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 130

def outbound_variant(kwargs)
  tag = @discriminator ? kwargs.fetch(@discriminator.to_sym, UNSET) : UNSET
  variant_for(tag) { |k| kwargs.key?(k.to_sym) && !UNSET.equal?(kwargs[k.to_sym]) }
end

.payload_tag(json_payload) (private)

The wire tag mapped back to its variant symbol (the table's key); an unrecognized tag falls through as-is so select misses and from_json raises.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 145

def payload_tag(json_payload)
  return UNSET unless @discriminator && json_payload.key?(@discriminator)

  wire = json_payload[@discriminator]
  @discriminator_values.key(wire) || wire
end

.presence(rules)

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 44

def presence(rules) = @presence = rules

.scalar_arm?(value) ⇒ Boolean (private)

A bare-scalar arm must be one of the literals the schema pinned for this union (scalar_values, e.g. input.Origin's "viewport" / "pointer"). The generator guarantees a non-object_only union declares them, so no runtime guard is needed here.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 107

def scalar_arm?(value)
  @scalar_values.include?(value)
end

.scalar_values(*values)

Declared (via the schema's scalarValues signal) on a non-object_only union whose bare-scalar arms are a fixed set of literals (input.Origin's "viewport" / "pointer"). An outbound scalar outside that set matches no arm, so it is a caller error.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 54

def scalar_values(*values) = @scalar_values = values

.select(json_payload) (private)

The discriminator value may legitimately be null (e.g. script.NullValue's "null" tag), so it is matched by key presence.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 124

def select(json_payload)
  variant_for(payload_tag(json_payload)) { |k| json_payload.key?(k) }
end

.valid_outbound?(value) ⇒ Boolean

Outbound mirror of from_json: is value one this union accepts? Any variant is accepted, and a variant that is itself a union recurses (e.g. LocalValue's RemoteReference fallback). A non-object_only union (e.g. input.Origin) also admits one of its pinned bare-scalar literals; an object (a Hash or another union's record) that matched no variant does not.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 96

def valid_outbound?(value)
  return true if variant_refs.any? { |ref| variant_accepts?(ref, value) }

  !@object_only && scalar_arm?(value)
end

.variant_accepts?(ref, value) ⇒ Boolean (private)

A variant that is itself a union recurses; a record variant is matched by instance.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 117

def variant_accepts?(ref, value)
  klass = (@variant_classes ||= {})[ref] ||= Protocol.const_get(ref)
  klass < Union ? klass.valid_outbound?(value) : value.is_a?(klass)
end

.variant_for(tag, &supplied) (private)

The matching variant's ref, or nil when none matches (the fallback if declared).

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 136

def variant_for(tag, &supplied)
  return @variants[tag] if !UNSET.equal?(tag) && @variants&.key?(tag)

  @presence&.each { |path, keys| return path if keys.all?(&supplied) }
  @fallback
end

.variant_refs (private)

Every variant's class name: the discriminated table, the presence paths, and the fallback.

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 112

def variant_refs
  @variant_refs ||= [*@variants&.values, *@presence&.keys, @fallback].compact
end

.variants(table)

[ GitHub ]

  
# File 'rb/lib/selenium/webdriver/bidi/serialization/union.rb', line 43

def variants(table) = @variants = table