structured_zstd/encoding/frame_emit_info.rs
1//! Structural metadata describing the layout of an emitted zstd frame.
2//!
3//! Surfaced via [`FrameCompressor::last_frame_emit_info`] (encode side)
4//! after every successful `compress()`. Lets storage-format consumers
5//! discover where each Block_Header / block body / optional content
6//! checksum lands in the byte buffer without re-parsing the frame
7//! themselves.
8//!
9//! Gated behind the `lsm` Cargo feature (default off) โ the
10//! `FrameCompressor` field that stores this info, the methods that
11//! return it, and these public types only exist when the feature is
12//! enabled. Without `lsm` the C FFI surface stays strict drop-in for
13//! donor `libzstd` v1.5.7.
14//!
15//! [`FrameCompressor::last_frame_emit_info`]: super::FrameCompressor::last_frame_emit_info
16
17extern crate alloc;
18
19use alloc::vec::Vec;
20
21pub use crate::blocks::block::BlockType;
22
23/// Layout of a single zstd block inside an emitted frame.
24///
25/// Offsets are absolute byte positions in the emitted-frame buffer:
26/// `offset_in_frame` points at the first byte of the 3-byte
27/// `Block_Header`, and the block body lives at
28/// `offset_in_frame + header_size .. offset_in_frame + header_size +
29/// body_size`. The arithmetic
30/// `offset_in_frame + header_size as u32 + body_size`
31/// is the byte offset of the next block (or, on the last block, of
32/// the trailing checksum / end of frame).
33///
34/// For RLE blocks the `body_size` is `1` (the single repeated byte
35/// on the wire); the spec's `Block_Size` field carries the logical
36/// repeat count instead and is surfaced separately as
37/// [`block_size_field`](Self::block_size_field).
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct FrameBlock {
40 /// Byte offset of this block's `Block_Header` within the emitted
41 /// frame buffer (frame-absolute, includes the bytes consumed by
42 /// the frame header / magic / FCS that precede the first block).
43 pub offset_in_frame: u32,
44 /// Size of the `Block_Header` in bytes. Always `3` today; carried
45 /// as a field so the API stays forward-compatible with any future
46 /// spec extension that widens the header.
47 pub header_size: u8,
48 /// Physical length of this block's body in bytes on the wire (does
49 /// NOT include `header_size`). For Raw / Compressed blocks this is
50 /// the number of bytes after the header; for RLE blocks this is
51 /// always `1` (the repeated byte itself, while the spec's
52 /// `Block_Size` field encodes the logical repeat count โ see
53 /// [`block_size_field`](Self::block_size_field)). The arithmetic
54 /// `offset_in_frame + header_size as u32 + body_size` always
55 /// lands on the next block boundary.
56 pub body_size: u32,
57 /// Raw `Block_Size` value from the 3-byte `Block_Header`. For Raw
58 /// and Compressed blocks this equals `body_size`; for RLE blocks
59 /// it's the logical repeat count (how many bytes the single
60 /// physical body byte expands to during decode) and will differ
61 /// from `body_size` (which is `1`).
62 pub block_size_field: u32,
63 /// Whether the block is Raw, RLE, or Compressed per RFC 8878
64 /// ยง3.1.1.2.1 (`Block_Type`).
65 pub block_type: BlockType,
66 /// `true` only on the final block of the frame (matches the
67 /// `Last_Block` flag in `Block_Header`).
68 pub last_block: bool,
69}
70
71/// Complete layout of an emitted zstd frame.
72///
73/// Captures the byte positions of the frame header, every block, and
74/// the optional trailing content checksum. The ranges are `u32` byte
75/// offsets into the emitted buffer (`compressed_data` sink of
76/// [`FrameCompressor`]).
77///
78/// [`FrameCompressor`]: super::FrameCompressor
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct FrameEmitInfo {
81 /// Byte range of the frame header (magic number + frame-header
82 /// fields). For magicless frames the magic is omitted but the
83 /// range still starts at offset 0.
84 pub frame_header_range: core::ops::Range<u32>,
85 /// One entry per emitted block, in stream order. The last entry
86 /// has `last_block = true`.
87 pub blocks: Vec<FrameBlock>,
88 /// Byte range of the trailing 4-byte content checksum (XXH64
89 /// truncated to low 32 bits). `None` if the frame was emitted
90 /// without `content_checksum`.
91 pub checksum_range: Option<core::ops::Range<u32>>,
92 /// Total emitted frame size in bytes (one past the last byte of
93 /// the frame).
94 pub total_size: u32,
95}