1use crate::error::{Error, Result};
16
17pub const SIZE_INDICATOR_MASK: u8 = 0x80;
20
21pub fn decode(bytes: &[u8]) -> Result<(usize, usize)> {
27 let first = *bytes
28 .first()
29 .ok_or(Error::InvalidLength("empty length_field"))?;
30 if first & SIZE_INDICATOR_MASK == 0 {
31 return Ok(((first & 0x7F) as usize, 1));
33 }
34 let n = (first & 0x7F) as usize;
36 if n == 0 {
37 return Err(Error::InvalidLength("indefinite length form not allowed"));
40 }
41 if n > 3 {
42 return Err(Error::InvalidLength("length_field_size exceeds 3 bytes"));
45 }
46 if bytes.len() < 1 + n {
47 return Err(Error::BufferTooShort {
48 need: 1 + n,
49 have: bytes.len(),
50 what: "length_field (long form)",
51 });
52 }
53 let mut value = 0usize;
54 for &b in &bytes[1..1 + n] {
55 value = (value << 8) | b as usize;
56 }
57 Ok((value, 1 + n))
58}
59
60#[must_use]
62pub fn encoded_len(value: usize) -> usize {
63 if value < 0x80 {
64 1
65 } else if value <= 0xFF {
66 2
67 } else if value <= 0xFFFF {
68 3
69 } else {
70 4
73 }
74}
75
76pub fn encode_into(value: usize, buf: &mut [u8]) -> Result<usize> {
81 let need = encoded_len(value);
82 if value > 0xFFFF {
83 return Err(Error::LengthTooLarge(value));
84 }
85 if buf.len() < need {
86 return Err(Error::OutputBufferTooSmall {
87 need,
88 have: buf.len(),
89 });
90 }
91 if value < 0x80 {
92 buf[0] = value as u8;
93 } else if value <= 0xFF {
94 buf[0] = SIZE_INDICATOR_MASK | 1;
95 buf[1] = value as u8;
96 } else {
97 buf[0] = SIZE_INDICATOR_MASK | 2;
98 buf[1] = (value >> 8) as u8;
99 buf[2] = value as u8;
100 }
101 Ok(need)
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn short_form_round_trip() {
110 for v in [0usize, 1, 0x7F] {
111 let mut buf = [0u8; 4];
112 let n = encode_into(v, &mut buf).unwrap();
113 assert_eq!(n, 1);
114 assert_eq!(encoded_len(v), 1);
115 let (decoded, hdr) = decode(&buf).unwrap();
116 assert_eq!((decoded, hdr), (v, 1));
117 }
118 }
119
120 #[test]
121 fn two_byte_form_round_trip() {
122 for v in [0x80usize, 0xFF] {
123 let mut buf = [0u8; 4];
124 let n = encode_into(v, &mut buf).unwrap();
125 assert_eq!(n, 2);
126 assert_eq!(buf[0], SIZE_INDICATOR_MASK | 1);
127 let (decoded, hdr) = decode(&buf).unwrap();
128 assert_eq!((decoded, hdr), (v, 2));
129 }
130 }
131
132 #[test]
133 fn three_byte_form_round_trip() {
134 for v in [0x100usize, 0x1234, 0xFFFF] {
135 let mut buf = [0u8; 4];
136 let n = encode_into(v, &mut buf).unwrap();
137 assert_eq!(n, 3);
138 assert_eq!(buf[0], SIZE_INDICATOR_MASK | 2);
139 let (decoded, hdr) = decode(&buf).unwrap();
140 assert_eq!((decoded, hdr), (v, 3));
141 }
142 }
143
144 #[test]
145 fn rejects_oversize() {
146 let mut buf = [0u8; 4];
147 assert!(matches!(
148 encode_into(0x1_0000, &mut buf),
149 Err(Error::LengthTooLarge(0x1_0000))
150 ));
151 }
152
153 #[test]
154 fn rejects_indefinite_and_wide() {
155 assert!(decode(&[0x80]).is_err()); assert!(decode(&[0x84, 0, 0, 0, 0]).is_err()); assert!(decode(&[]).is_err());
158 assert!(decode(&[0x82, 0x12]).is_err()); }
160
161 #[test]
162 fn mutating_a_byte_changes_decode() {
163 let mut buf = [0u8; 4];
164 encode_into(0x1234, &mut buf).unwrap();
165 let (a, _) = decode(&buf).unwrap();
166 buf[2] ^= 0xFF;
167 let (b, _) = decode(&buf).unwrap();
168 assert_ne!(a, b);
169 }
170}