phantom_protocol/transport/legs/embedded/
framing.rs1pub const HEADER_LEN: usize = 4;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum FramingError {
19 FrameTooLarge {
22 len: usize,
24 capacity: usize,
26 },
27}
28
29pub fn encode_header(
32 payload_len: usize,
33 capacity: usize,
34) -> Result<[u8; HEADER_LEN], FramingError> {
35 if payload_len > capacity {
36 return Err(FramingError::FrameTooLarge {
37 len: payload_len,
38 capacity,
39 });
40 }
41 match u32::try_from(payload_len) {
42 Ok(len) => Ok(len.to_be_bytes()),
43 Err(_) => Err(FramingError::FrameTooLarge {
44 len: payload_len,
45 capacity,
46 }),
47 }
48}
49
50pub fn decode_header(header: &[u8; HEADER_LEN], capacity: usize) -> Result<usize, FramingError> {
53 let len = u32::from_be_bytes(*header) as usize;
54 if len > capacity {
55 return Err(FramingError::FrameTooLarge { len, capacity });
56 }
57 Ok(len)
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn encode_header_writes_big_endian_length() {
66 let header = encode_header(0x0102_0304, 0x1000_0000).expect("within capacity");
67 assert_eq!(header, [0x01, 0x02, 0x03, 0x04]);
68 }
69
70 #[test]
71 fn encode_header_rejects_length_over_capacity() {
72 let err = encode_header(2000, 1024).expect_err("2000 > 1024 capacity");
73 assert_eq!(
74 err,
75 FramingError::FrameTooLarge {
76 len: 2000,
77 capacity: 1024
78 }
79 );
80 }
81
82 #[test]
83 #[cfg(target_pointer_width = "64")]
84 fn encode_header_rejects_length_over_u32_max() {
85 let huge = u32::MAX as usize + 1;
89 let err = encode_header(huge, usize::MAX).expect_err("over u32::MAX wire limit");
90 assert_eq!(
91 err,
92 FramingError::FrameTooLarge {
93 len: huge,
94 capacity: usize::MAX
95 }
96 );
97 }
98
99 #[test]
100 fn encode_decode_round_trips() {
101 let capacity = 0x1000_0000;
102 for len in [0_usize, 1, 255, 0x0102_0304] {
103 let header = encode_header(len, capacity).expect("within capacity");
104 let decoded = decode_header(&header, capacity).expect("within capacity");
105 assert_eq!(decoded, len, "round-trip failed for len {len}");
106 }
107 }
108
109 #[test]
110 fn decode_header_rejects_length_over_capacity() {
111 let err = decode_header(&[0x00, 0x00, 0x08, 0x00], 1024).expect_err("2048 > 1024 capacity");
113 assert_eq!(
114 err,
115 FramingError::FrameTooLarge {
116 len: 2048,
117 capacity: 1024
118 }
119 );
120 }
121}