sofab.visitor module

Visitor-pattern decode driver — the language-idiomatic pull alternative.

ARCHITECTURE.md lists the visitor pattern as a recommended decoder shape:

“The decoder calls typed visitor methods on a user-supplied object.

Pull-reading becomes the visitor receives the value or chooses to skip.”

Visitor is a base class whose hooks all default to no-op (the value is still consumed, so an unhandled field is transparently skipped). Subclass it and override only the fields you care about, then hand it to sofab.Decoder.drive().

Two control hooks let a visitor decline work before the value is decoded — so skipping a 10k-element array or a deep sub-tree costs nothing:

  • Visitor.on_field() — return False to skip a scalar/fixlen/array field instead of decoding it.

  • Visitor.on_sequence_begin() — return False to skip the entire nested sequence (its matching end is consumed too, so on_sequence_end is not called for a skipped sequence).

The driver itself is layered on the public pull API, so it inherits the same “advance a cursor over a contiguous buffer” hot path as direct pull decoding.

class sofab.visitor.Visitor[source]

Bases: object

Base visitor: override the hooks for the fields you handle.

Every hook is keyed by the wire type the decoder recovered. field_id is the decoded field id. Unhandled hooks default to a no-op, which still consumes the value (so unknown fields are skipped safely).

on_field(field)[source]

Called for every non-sequence field before its value is decoded. Return False to skip the value entirely; any other return proceeds to decode it and dispatch to the typed hook below.

Parameters:

field (Field)

Return type:

bool | None

on_sequence_begin(field_id)[source]

A nested sequence is opening. Return False to skip the whole sub-tree (its end is consumed, on_sequence_end is not called).

Parameters:

field_id (int)

Return type:

bool | None

on_sequence_end()[source]

The current nested sequence closed.

Return type:

None

on_unsigned(field_id, value)[source]

Handle a decoded unsigned-integer field.

Parameters:
  • field_id (int)

  • value (int)

Return type:

None

on_signed(field_id, value)[source]

Handle a decoded signed-integer field.

Parameters:
  • field_id (int)

  • value (int)

Return type:

None

on_float32(field_id, value)[source]

Handle a decoded 32-bit float field.

Parameters:
  • field_id (int)

  • value (float)

Return type:

None

on_float64(field_id, value)[source]

Handle a decoded 64-bit float field.

Parameters:
  • field_id (int)

  • value (float)

Return type:

None

on_string(field_id, value)[source]

Handle a decoded UTF-8 string field.

Parameters:
  • field_id (int)

  • value (str)

Return type:

None

on_bytes(field_id, value)[source]

Handle a decoded raw byte-blob field.

Parameters:
  • field_id (int)

  • value (bytes)

Return type:

None

on_unsigned_array(field_id, values)[source]

Handle a decoded unsigned-integer array field.

Parameters:
  • field_id (int)

  • values (list[int])

Return type:

None

on_signed_array(field_id, values)[source]

Handle a decoded signed-integer array field.

Parameters:
  • field_id (int)

  • values (list[int])

Return type:

None

on_float32_array(field_id, values)[source]

Handle a decoded 32-bit float array field.

Parameters:
  • field_id (int)

  • values (list[float])

Return type:

None

on_float64_array(field_id, values)[source]

Handle a decoded 64-bit float array field.

Parameters:
  • field_id (int)

  • values (list[float])

Return type:

None