sofab.decoder module¶
SofaBuffers pull decoder (Go-style IStream equivalent).
The decoder reads from any object exposing read(n) -> bytes (a file, a
socket made file-like, an io.BytesIO, or a chunk-feeding wrapper). It pulls
exactly what it needs, so it satisfies the format’s streaming requirement for
blocking readers; large blob/string/array payloads are read in bulk.
Hot-path model — “advance a cursor over a contiguous buffer” (protobuf’s
trick). Incoming bytes are accumulated into a single contiguous buffer
(self._buf) and parsed by advancing an integer cursor (self._pos) with
direct indexing — no per-byte function call, no intermediate copies. When the
cursor reaches the end mid-item the decoder transparently refills from the
reader and continues, so the same code path serves both a fully-buffered
message and a reader that dribbles one byte at a time. See _varint /
_read_varints / _read_exact below.
Typical use:
dec = Decoder(reader)
while (field := dec.next()) is not None:
if field.id == 1:
value = dec.unsigned()
else:
dec.skip()
- class sofab.decoder.Decoder(reader, *, chunk_size=65536, max_array_count=None, max_string_len=None, max_blob_len=None)[source]¶
Bases:
objectPull-decodes a SofaBuffers stream field by field.
Call
next()to advance to each field, then one of the typed read methods (unsigned(),string(),read_float64_array(), …) to consume its value, orskip()to discard it. Alternatively hand asofab.Visitortodrive()for callback-style decoding.- Parameters:
reader (_Reader)
chunk_size (int)
max_array_count (int | None)
max_string_len (int | None)
max_blob_len (int | None)
- next()[source]¶
Advance to the next field. Returns
Noneat clean EOF.Any value left unconsumed from the previous field is skipped first.
- Return type:
Field | None
- skip()[source]¶
Skip the current field’s value, or an entire (nested) sequence if the current field is a sequence start.
- Return type:
None
- drive(visitor)[source]¶
Pull the whole stream, dispatching each field to
visitor’s typed hooks (seesofab.Visitor). A visitor may decline a field viaon_field/on_sequence_beginreturningFalseto skip it without paying the decode cost.- Parameters:
visitor (sofab.Visitor)
- Return type:
None
- unsigned()[source]¶
Consume the current field as an unsigned integer.
Raises
SofaStateErrorif the current field is not unsigned.- Return type:
int
- signed()[source]¶
Consume the current field as a ZigZag-decoded signed integer.
Raises
SofaStateErrorif the current field is not signed.- Return type:
int
- bool()[source]¶
Consume the current unsigned field as a boolean (non-zero is true).
- Return type:
bool
- float32()[source]¶
Consume the current fixlen field as a 32-bit IEEE-754 float.
Raises
SofaStateErrorif the field is not an fp32 fixlen, orSofaDecodeErrorif its payload is not 4 bytes.- Return type:
float
- float64()[source]¶
Consume the current fixlen field as a 64-bit IEEE-754 float.
Raises
SofaStateErrorif the field is not an fp64 fixlen, orSofaDecodeErrorif its payload is not 8 bytes.- Return type:
float
- fixlen_len()[source]¶
Return the current fixlen field’s payload byte length without consuming it.
The length is read straight from the field’s length header, so this is a pure peek: it does not advance the decoder and a following
string()/bytes()/float32()/float64()still reads the same field. It lets a caller bound a string or blob against its schemamaxlenusing the exact wire byte length the decoder already parsed — checked before allocation, and without re-encoding a decodedstrjust to measure it (the string field is UTF-8 on the wire, so the payload byte length is the lengthmaxlenbounds).Raises
SofaStateErrorif the current field is not a fixlen value.- Return type:
int
- string()[source]¶
Consume the current fixlen field as a UTF-8 decoded string.
Raises
SofaStateErrorif the field is not a STRING fixlen, orSofaDecodeErrorif the payload is not valid UTF-8.- Return type:
str
- bytes()[source]¶
Consume the current fixlen field as a raw byte blob.
Raises
SofaStateErrorif the field is not a BLOB fixlen.- Return type:
bytes
- read_unsigned_array()[source]¶
Consume the current field as a list of unsigned integers.
Raises
SofaStateErrorif the field is not an unsigned array.- Return type:
list[int]
- read_signed_array()[source]¶
Consume the current field as a list of ZigZag-decoded signed integers.
Raises
SofaStateErrorif the field is not a signed array.- Return type:
list[int]