sofab package

Submodules

Module contents

SofaBuffers — runtime for the SofaBuffers binary wire format.

Byte-for-byte compatible with the C/C++/Rust/Go/Java/C# core libraries. Import the Encoder and Decoder and the wire-format types from here.

Encoder / Decoder resolve to the compiled native accelerator (sofab._speedups, built by Cython) when it is available, and to the pure-Python implementations otherwise — the two are byte-for-byte interchangeable (see IMPL).

class sofab.Encoder

Bases: object

Native encoder — see sofab.encoder.Encoder for the full contract.

Two construction models, byte-identical to the pure-Python encoder:

  • Encoder(writer=None, sticky=False) — Go-style growable buffer; bytes accumulate in an internal C buffer drained to writer on flush() (or read back via getvalue()).

  • Encoder.over_buffer(buffer, offset, flush) — Rust/C-style; writes into a caller-owned bytearray, draining through flush when it fills.

buffer_set(buffer, offset=0)
bytes_used()
error
flush()
getvalue()
classmethod over_buffer(buffer, offset=0, flush=None, *, sticky=False)
write_bool(field_id, value)
write_bytes(field_id, data)
write_float32(field_id, value)
write_float32_array(field_id, values)
write_float64(field_id, value)
write_float64_array(field_id, values)
write_sequence_begin_lazy(field_id)
write_sequence_end()
write_sequence_end_keep()
write_signed(field_id, value)
write_signed_array(field_id, values)
write_string(field_id, text)
write_unsigned(field_id, value)
write_unsigned_array(field_id, values)
class sofab.Decoder

Bases: object

Native pull decoder — see sofab.decoder.Decoder for the contract.

Reads from any object exposing read(n) -> bytes. Incoming bytes are held in one contiguous buffer and parsed by advancing a C cursor with direct pointer indexing; it refills transparently from the reader when it runs off the end mid-item, so it serves both a fully-buffered message and a reader that dribbles one byte at a time.

bool()
bytes()
drive(visitor)
field
fixlen_len()
float32()
float64()
next()
read_float32_array()
read_float64_array()
read_signed_array()
read_unsigned_array()
signed()
skip()
string()
unsigned()
class sofab.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

class sofab.Field

Bases: object

Describes the field the decoder is currently positioned on.

Byte-for-byte compatible attribute surface with sofab.types.Field.

count
id
size
subtype
type
class sofab.WireType(*values)[source]

Bases: IntEnum

The 3 low bits of a field header.

UNSIGNED = 0
SIGNED = 1
FIXLEN = 2
ARRAY_UNSIGNED = 3
ARRAY_SIGNED = 4
ARRAY_FIXLEN = 5
SEQUENCE_START = 6
SEQUENCE_END = 7
class sofab.FixlenSubtype(*values)[source]

Bases: IntEnum

The 3 low bits of a fixlen length header.

FP32 = 0
FP64 = 1
STRING = 2
BLOB = 3
exception sofab.SofaError[source]

Bases: Exception

Base class for all SofaBuffers errors.

exception sofab.SofaDecodeError[source]

Bases: SofaError

Malformed input — invalid regardless of what bytes might follow: an overflowing (>64-bit) varint, a bad fixlen subtype, an out-of-range id/count/length, invalid UTF-8, nesting past MAX_DEPTH, or a dangling sequence end (MESSAGE_SPEC §7 INVALID).

This is deliberately not raised for truncation — bytes that simply end inside a field are SofaIncompleteError (§7 INCOMPLETE), a distinct non-error outcome that is not a subclass of this class, so except SofaDecodeError does not catch it.

exception sofab.SofaIncompleteError[source]

Bases: SofaError

Truncated input — the bytes end inside a field (MESSAGE_SPEC §7 INCOMPLETE): an unterminated varint, a fixlen/array payload shorter than its declared length, an array element that runs off the end, or a nested sequence that is never closed.

This is not malformed: more bytes could complete the message, and the caller owns end-of-input. It is a sibling of SofaDecodeError under SofaError, not a subclass of it, so callers can tell “need more bytes” apart from “these bytes are garbage”.

exception sofab.SofaLimitError[source]

Bases: SofaError

A wire-declared array count or fixlen (string/blob) length exceeded a receiver-configured decode limit (Decoder(max_array_count=…, max_string_len=…, max_blob_len=…)).

This is a policy rejection, not wire malformation: the bytes are perfectly well-formed and would decode fine with the limit unset — the receiver simply declined to allocate for them. It is therefore a sibling of SofaDecodeError under SofaError, not a subclass of it, so except SofaDecodeError does not catch it and differential fuzzing does not see a limit rejection as a conformance divergence from another engine.

exception sofab.SofaRangeError[source]

Bases: SofaError

A value (or id/count) is outside the permitted range on encode.

exception sofab.SofaStateError[source]

Bases: SofaError

API misuse, e.g. reading a value of the wrong type for the current field, or ending a sequence that was never started.

exception sofab.SofaBufferError[source]

Bases: SofaError

A fixed encoder buffer filled up and no flush sink was provided.

sofab.zigzag_encode(v)[source]

Map a signed int to unsigned: (n << 1) ^ (n >> 63) (64-bit).

Parameters:

v (int)

Return type:

int

sofab.zigzag_decode(u)[source]

Inverse of zigzag_encode(): (z >> 1) ^ -(z & 1).

Parameters:

u (int)

Return type:

int

sofab.IMPL = 'native'

"native" when the compiled sofab._speedups extension is in use, else "python".

Type:

Which implementation Encoder/Decoder resolve to