pub struct BcpDecoder;Expand description
Synchronous BCP decoder — parses a complete in-memory payload.
The decoder reads an entire BCP payload from a byte slice and
produces a DecodedPayload containing the header and all typed
blocks. It is the inverse of
BcpEncoder::encode from the bcp-encoder crate.
Decoding proceeds in four steps:
- Header: Validate and parse the 8-byte file header (magic number, version, flags, reserved byte).
- Whole-payload decompression: If the header’s
COMPRESSEDflag (bit 0) is set, decompress all bytes after the header with zstd before parsing block frames. - Block frames: Iterate block frames by reading
BlockFrameenvelopes. For each frame:- If
COMPRESSED(bit 1): decompress the body with zstd. - If
IS_REFERENCE(bit 2): resolve the 32-byte BLAKE3 hash against the content store to recover the original body. - Extract the summary sub-block if
HAS_SUMMARY(bit 0) is set. - Deserialize the body into the corresponding
BlockContent.
- If
- Termination: Stop when an END sentinel (type=0xFF) is encountered. Detect and report trailing data after the sentinel.
Unknown block types are captured as BlockContent::Unknown and do
not cause errors — this is the forward compatibility guarantee from
RFC §3, P1 Schema Evolution.
§Example
use bcp_encoder::BcpEncoder;
use bcp_decoder::BcpDecoder;
use bcp_types::enums::{Lang, Role};
let payload = BcpEncoder::new()
.add_code(Lang::Rust, "main.rs", b"fn main() {}")
.add_conversation(Role::User, b"hello")
.encode()
.unwrap();
let decoded = BcpDecoder::decode(&payload).unwrap();
assert_eq!(decoded.blocks.len(), 2);Implementations§
Source§impl BcpDecoder
impl BcpDecoder
Sourcepub fn decode(payload: &[u8]) -> Result<DecodedPayload, DecodeError>
pub fn decode(payload: &[u8]) -> Result<DecodedPayload, DecodeError>
Decode a complete BCP payload from a byte slice.
This is the standard entry point for payloads that do not contain
content-addressed (reference) blocks. If the payload contains
blocks with the IS_REFERENCE flag, use
decode_with_store instead.
Handles whole-payload and per-block zstd decompression transparently.
§Errors
DecodeError::InvalidHeaderif the magic, version, or reserved byte is wrong.DecodeError::Wireif a block frame is malformed.DecodeError::Typeif a block body fails TLV deserialization.DecodeError::DecompressFailedif zstd decompression fails.DecodeError::DecompressionBombif decompressed size exceeds the safety limit.DecodeError::MissingContentStoreif a reference block is encountered (usedecode_with_storeinstead).DecodeError::MissingEndSentinelif the payload ends without an END block.DecodeError::TrailingDataif extra bytes follow the END sentinel.
Sourcepub fn decode_with_store(
payload: &[u8],
store: &dyn ContentStore,
) -> Result<DecodedPayload, DecodeError>
pub fn decode_with_store( payload: &[u8], store: &dyn ContentStore, ) -> Result<DecodedPayload, DecodeError>
Decode a payload that may contain content-addressed blocks.
Same as decode, but accepts a ContentStore
for resolving IS_REFERENCE blocks. When a block’s body is a
32-byte BLAKE3 hash, the decoder looks it up in the store to
retrieve the original body bytes.
§Errors
All errors from decode, plus:
DecodeError::UnresolvedReferenceif a hash is not found in the content store.