Skip to main content

streaming_crypto/core_api/stream_v2/segmenting/
encode.rs

1use byteorder::{LittleEndian, WriteBytesExt};
2use bytes::Bytes;
3
4use crate::stream_v2::segmenting::{SegmentHeader, types::SegmentError};
5
6/// Encode a segment record into canonical wire format.
7///
8/// Layout:
9///
10/// ```text
11/// [ segment_index (4) ]
12/// [ bytes_len     (4) ]
13/// [ wire_len      (4) ]
14/// [ wire_crc32    (4) ]
15/// [ frame_count   (2) ]
16/// [ digest_alg    (2) ]
17/// [ flags         (2) ]
18/// [ header_crc32  (4) ]
19/// ```
20pub fn encode_segment(
21    header: &SegmentHeader,
22    segment_wire: &Bytes,
23) -> Result<Vec<u8>, SegmentError> {
24    let expected = SegmentHeader::LEN + header.wire_len() as usize;
25
26    if segment_wire.len() != header.wire_len() as usize {
27        return Err(SegmentError::LengthMismatch {
28            expected,
29            actual: segment_wire.len(),
30        });
31    }
32
33    let mut wire = Vec::with_capacity(expected);
34
35    // --- Header ---
36    wire.write_u32::<LittleEndian>(header.segment_index()).unwrap();
37    wire.write_u32::<LittleEndian>(header.bytes_len()).unwrap();
38    wire.write_u32::<LittleEndian>(header.wire_len()).unwrap();
39    wire.write_u32::<LittleEndian>(header.wire_crc32()).unwrap();
40    wire.write_u32::<LittleEndian>(header.frame_count()).unwrap();
41    wire.write_u16::<LittleEndian>(header.digest_alg()).unwrap();
42    wire.write_u16::<LittleEndian>(header.flags().bits()).unwrap();
43    wire.write_u32::<LittleEndian>(header.header_crc32()).unwrap();
44
45    // --- Body ---
46    wire.extend_from_slice(segment_wire);
47
48    // --- Validation ---
49    debug_assert_eq!(wire.len(), expected);
50
51    Ok(wire)
52
53    // ### 🔥 Why this is better
54
55    // * Encoding no longer **requires ownership**
56    // * Segment_wire can be:
57
58    // * `Vec<u8>`
59    // * `Bytes`
60    // * slice from another buffer
61    // * Header + body are **logically separated**
62}