Expand description
PackStream — Bolt’s value encoding — and Bolt’s message chunking.
Hand-written because the whole codec is ~300 lines and the property that matters most is one no published crate states: a peer cannot make the decoder recurse without bound or allocate what the bytes do not contain. Two guards carry that:
- Depth. Lists, maps and structures nest, and one marker byte opens a level (
0x91is a one-element list), so ~1 KB on the wire buys a thousand frames of recursion.decoderecurses with an explicit counter and refuses pastMAX_PACKSTREAM_DEPTH. Real Bolt traffic nests three or four deep (a RUN’s parameter map holding a list of maps). - Declared lengths. A
0xD6list header declares a 32-bit element count in four bytes. Every count and byte length is checked against the bytes remaining before anything is allocated: an element needs at least one byte, a map entry at least two, so a count larger than that is refused asDecodeError::DeclaredLengthExceedsInputandVec::with_capacityis only ever asked for what could actually be present.
Chunking (Dechunker) carries the third bound: a message is the concatenation of chunks
(each a 2-byte big-endian size and that many bytes) ended by a zero-size chunk, and the total
is capped at MAX_MESSAGE_BYTES as chunks arrive, so a peer that never sends the
terminating zero cannot grow the buffer past it.
Encoding always picks the smallest form: integers in -16..=127 are one byte, strings under
16 bytes use the tiny marker, and so on. What NetGet encodes is either something it decoded
(so already depth-bounded) or a JSON value the model wrote, which bolt::values bounds to the
same depth before building it.
Structs§
- Dechunker
- Reassembles chunked messages from a byte stream, enforcing
MAX_MESSAGE_BYTESas chunks arrive.
Enums§
- Decode
Error - Why a byte sequence is not a PackStream value.
- Frame
Error - Why the byte stream is not a sequence of acceptable messages.
- Value
- A PackStream value.
Constants§
- MAX_
CHUNK_ BYTES - The largest payload one chunk can carry (its size field is a
u16). - MAX_
MESSAGE_ BYTES - Largest message, summed over its chunks, the server accepts. Neo4j imposes no fixed limit of
its own; 1 MiB is several thousand times what
cypher-shellsends for an interactive query and still room for a RUN carrying a sizeable parameter map. - MAX_
PACKSTREAM_ DEPTH - Deepest nesting of lists, maps and structures the decoder accepts. A message’s own top-level structure is depth 1, its fields depth 2, and so on.
Functions§
- chunk
- Frame one encoded message as chunks of at most
MAX_CHUNK_BYTES, ended by00 00. - decode
- Decode exactly one value occupying the whole of
bytes. - encode
- Encode one value, choosing the smallest representation.
- message_
bytes - Encode a value and frame it as one chunked message.
- to_
bytes - Encode to a fresh buffer.