datastream/binary
Framing operations on Stream(BitArray).
Real byte sources (sockets, files, pipes) deliver bytes in arbitrary chunks. A frame may straddle chunks, several frames may sit in one chunk, or a chunk may end mid-prefix. Every framing combinator here owns the buffer needed to reassemble.
All combinators are lazy and chunk-boundary-aware; none of them materialises the full input.
Types
Truncation surfaced by length_prefixed when the input ends
mid-frame.
expected is the number of bytes the combinator was waiting for —
either prefix_size (when the prefix itself was short) or the
declared payload length (when the prefix was complete but the
payload was short). got is the number of bytes the stream
actually delivered toward that requirement (always < expected).
pub type IncompleteFrame {
IncompleteFrame(expected: Int, got: Int)
}
Constructors
-
IncompleteFrame(expected: Int, got: Int)
Values
pub fn bytes(
over stream: datastream.Stream(BitArray),
) -> datastream.Stream(Int)
Yield each byte of each chunk in order, as Int in 0..255.
The trivial degenerate framing: bridges from Stream(BitArray) to
Stream(Int) so callers can move into the byte-stream-shaped world
without writing the per-byte unfold themselves.
pub fn delimited(
over stream: datastream.Stream(BitArray),
on delimiter: BitArray,
) -> datastream.Stream(BitArray)
Yield delimiter-separated frames in source order, preserving empty frames between consecutive delimiters and the trailing frame after a trailing delimiter. The delimiter itself is NOT included in any emitted frame.
If the input does not end with a delimiter, the trailing partial frame is emitted as the last element.
pub fn fixed_size(
over stream: datastream.Stream(BitArray),
size size: Int,
) -> datastream.Stream(BitArray)
Yield successive size-byte frames in source order. The trailing
partial frame on EOF is discarded — by definition a fixed-size
framing combinator cannot emit a frame of fewer than size bytes.
size MUST be >= 1. Other values are rejected at construction
time with a panic per the datastream module-level
invalid-argument policy.
pub fn length_prefixed(
over stream: datastream.Stream(BitArray),
prefix_size prefix_size: Int,
) -> datastream.Stream(Result(BitArray, IncompleteFrame))
Read a prefix_size byte big-endian unsigned length, then yield
the next length bytes as a frame, wrapped in Ok.
prefix_size MUST be one of {1, 2, 4, 8}. Other values are
rejected at construction time with a panic per the datastream
module-level invalid-argument policy.
If the input ends mid-frame (the prefix is shorter than
prefix_size bytes, or the payload is shorter than the declared
length), the stream emits exactly one
Error(IncompleteFrame(expected:, got:)) element before halting,
so callers can distinguish “no more frames” from “truncated final
frame”. The Stream(Result(_, _)) shape mirrors text.utf8_decode;
chain fold.collect_result to stop on the first truncation, or
fold.partition_result to drive the stream to completion and split
well-formed frames from the incomplete tail.