1use crate::error::{Error, Result};
16
17pub const SIZE_INDICATOR_MASK: u8 = 0x80;
20
21pub const MAX_LENGTH_OCTETS: u8 = 4;
25
26pub const MAX_LENGTH: usize = 0xFFFF;
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize))]
43#[non_exhaustive]
44pub enum LengthForm {
45 #[default]
48 Minimal,
49 Long {
52 octets: u8,
55 },
56}
57
58impl LengthForm {
59 #[must_use]
61 pub const fn is_minimal(&self) -> bool {
62 matches!(self, Self::Minimal)
63 }
64
65 #[must_use]
67 pub fn name(&self) -> &'static str {
68 match self {
69 Self::Minimal => "minimal",
70 Self::Long { .. } => "long",
71 }
72 }
73}
74broadcast_common::impl_spec_display!(LengthForm);
75
76pub fn decode(bytes: &[u8]) -> Result<(usize, usize)> {
82 let (value, hdr, _) = decode_form(bytes)?;
83 Ok((value, hdr))
84}
85
86pub fn decode_form(bytes: &[u8]) -> Result<(usize, usize, LengthForm)> {
95 let first = *bytes
96 .first()
97 .ok_or(Error::InvalidLength("empty length_field"))?;
98 if first & SIZE_INDICATOR_MASK == 0 {
99 return Ok(((first & 0x7F) as usize, 1, LengthForm::Minimal));
101 }
102 let n = (first & 0x7F) as usize;
104 if n == 0 {
105 return Err(Error::InvalidLength("indefinite length form not allowed"));
108 }
109 if n > MAX_LENGTH_OCTETS as usize {
110 return Err(Error::InvalidLength(
111 "length_field_size exceeds 4 length octets",
112 ));
113 }
114 if bytes.len() < 1 + n {
115 return Err(Error::BufferTooShort {
116 need: 1 + n,
117 have: bytes.len(),
118 what: "length_field (long form)",
119 });
120 }
121 let mut value = 0usize;
122 for &b in &bytes[1..1 + n] {
123 value = (value << 8) | b as usize;
124 }
125 if value > MAX_LENGTH {
126 return Err(Error::LengthTooLarge(value));
127 }
128 let form = if n == minimal_octets(value) && value >= 0x80 {
132 LengthForm::Minimal
133 } else {
134 LengthForm::Long { octets: n as u8 }
135 };
136 Ok((value, 1 + n, form))
137}
138
139const fn minimal_octets(value: usize) -> usize {
141 if value <= 0xFF { 1 } else { 2 }
142}
143
144#[must_use]
146pub fn encoded_len(value: usize) -> usize {
147 if value < 0x80 {
148 1
149 } else if value <= 0xFF {
150 2
151 } else if value <= 0xFFFF {
152 3
153 } else {
154 4
157 }
158}
159
160#[must_use]
167pub fn encoded_len_with(value: usize, form: LengthForm) -> usize {
168 match form {
169 LengthForm::Minimal => encoded_len(value),
170 LengthForm::Long { octets } => 1 + octets as usize,
171 }
172}
173
174pub fn encode_with(value: usize, form: LengthForm, buf: &mut [u8]) -> Result<usize> {
185 let LengthForm::Long { octets } = form else {
186 return encode_into(value, buf);
187 };
188 if value > MAX_LENGTH {
189 return Err(Error::LengthTooLarge(value));
190 }
191 if octets == 0 || octets > MAX_LENGTH_OCTETS {
192 return Err(Error::InvalidLength("length_field_size must be 1..=4"));
193 }
194 let n = octets as usize;
195 if n < 4 && value >> (8 * n) != 0 {
196 return Err(Error::InvalidLength(
197 "length value does not fit the recorded length_field_size",
198 ));
199 }
200 if value >= 0x80 && n == minimal_octets(value) {
206 return Err(Error::InvalidLength(
207 "Long form with the minimal number of octets is LengthForm::Minimal",
208 ));
209 }
210 let need = 1 + n;
211 if buf.len() < need {
212 return Err(Error::OutputBufferTooSmall {
213 need,
214 have: buf.len(),
215 });
216 }
217 buf[0] = SIZE_INDICATOR_MASK | octets;
218 for (i, slot) in buf[1..need].iter_mut().enumerate() {
219 let shift = 8 * (n - 1 - i);
220 *slot = (value >> shift) as u8;
221 }
222 Ok(need)
223}
224
225pub fn encode_into(value: usize, buf: &mut [u8]) -> Result<usize> {
230 let need = encoded_len(value);
231 if value > 0xFFFF {
232 return Err(Error::LengthTooLarge(value));
233 }
234 if buf.len() < need {
235 return Err(Error::OutputBufferTooSmall {
236 need,
237 have: buf.len(),
238 });
239 }
240 if value < 0x80 {
241 buf[0] = value as u8;
242 } else if value <= 0xFF {
243 buf[0] = SIZE_INDICATOR_MASK | 1;
244 buf[1] = value as u8;
245 } else {
246 buf[0] = SIZE_INDICATOR_MASK | 2;
247 buf[1] = (value >> 8) as u8;
248 buf[2] = value as u8;
249 }
250 Ok(need)
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256
257 #[test]
258 fn short_form_round_trip() {
259 for v in [0usize, 1, 0x7F] {
260 let mut buf = [0u8; 4];
261 let n = encode_into(v, &mut buf).unwrap();
262 assert_eq!(n, 1);
263 assert_eq!(encoded_len(v), 1);
264 let (decoded, hdr) = decode(&buf).unwrap();
265 assert_eq!((decoded, hdr), (v, 1));
266 }
267 }
268
269 #[test]
270 fn two_byte_form_round_trip() {
271 for v in [0x80usize, 0xFF] {
272 let mut buf = [0u8; 4];
273 let n = encode_into(v, &mut buf).unwrap();
274 assert_eq!(n, 2);
275 assert_eq!(buf[0], SIZE_INDICATOR_MASK | 1);
276 let (decoded, hdr) = decode(&buf).unwrap();
277 assert_eq!((decoded, hdr), (v, 2));
278 }
279 }
280
281 #[test]
282 fn three_byte_form_round_trip() {
283 for v in [0x100usize, 0x1234, 0xFFFF] {
284 let mut buf = [0u8; 4];
285 let n = encode_into(v, &mut buf).unwrap();
286 assert_eq!(n, 3);
287 assert_eq!(buf[0], SIZE_INDICATOR_MASK | 2);
288 let (decoded, hdr) = decode(&buf).unwrap();
289 assert_eq!((decoded, hdr), (v, 3));
290 }
291 }
292
293 #[test]
294 fn rejects_oversize() {
295 let mut buf = [0u8; 4];
296 assert!(matches!(
297 encode_into(0x1_0000, &mut buf),
298 Err(Error::LengthTooLarge(0x1_0000))
299 ));
300 }
301
302 #[test]
303 fn rejects_indefinite_and_wide() {
304 assert!(decode(&[0x80]).is_err()); assert!(decode(&[0x85, 0, 0, 0, 0, 0]).is_err()); assert!(decode(&[]).is_err());
307 assert!(decode(&[0x82, 0x12]).is_err()); }
309
310 #[test]
315 fn every_form_round_trips_byte_exactly() {
316 let cases: &[(&[u8], usize, LengthForm)] = &[
317 (&[0x05], 5, LengthForm::Minimal),
318 (&[0x7F], 127, LengthForm::Minimal),
319 (&[0x81, 0x80], 0x80, LengthForm::Minimal),
320 (&[0x81, 0xFF], 0xFF, LengthForm::Minimal),
321 (&[0x82, 0x01, 0x00], 0x100, LengthForm::Minimal),
322 (&[0x82, 0xFF, 0xFF], 0xFFFF, LengthForm::Minimal),
323 (&[0x81, 0x05], 5, LengthForm::Long { octets: 1 }),
325 (&[0x81, 0x00], 0, LengthForm::Long { octets: 1 }),
326 (&[0x82, 0x00, 0x09], 9, LengthForm::Long { octets: 2 }),
328 (&[0x82, 0x00, 0x80], 0x80, LengthForm::Long { octets: 2 }),
329 (
330 &[0x83, 0x00, 0x01, 0x00],
331 0x100,
332 LengthForm::Long { octets: 3 },
333 ),
334 (&[0x83, 0x00, 0x00, 0x09], 9, LengthForm::Long { octets: 3 }),
335 (
336 &[0x84, 0x00, 0x00, 0x00, 0x09],
337 9,
338 LengthForm::Long { octets: 4 },
339 ),
340 ];
341 for &(wire, value, form) in cases {
342 let (v, hdr, f) = decode_form(wire).unwrap();
343 assert_eq!((v, hdr, f), (value, wire.len(), form), "{wire:02X?}");
344 let mut buf = [0u8; 8];
345 let n = encode_with(value, form, &mut buf).unwrap();
346 assert_eq!(&buf[..n], wire, "re-encode {wire:02X?}");
347 assert_eq!(encoded_len_with(value, form), wire.len());
348 }
349 }
350
351 #[test]
353 fn minimal_form_matches_encode_into() {
354 for v in [0usize, 1, 0x7F, 0x80, 0xFF, 0x100, 0x1234, 0xFFFF] {
355 let (mut a, mut b) = ([0u8; 4], [0u8; 4]);
356 let na = encode_into(v, &mut a).unwrap();
357 let nb = encode_with(v, LengthForm::default(), &mut b).unwrap();
358 assert_eq!(a[..na], b[..nb]);
359 }
360 }
361
362 #[test]
363 fn encode_with_rejects_a_form_that_cannot_hold_the_value() {
364 let mut buf = [0u8; 8];
365 assert!(encode_with(0x100, LengthForm::Long { octets: 1 }, &mut buf).is_err());
367 assert!(encode_with(0x80, LengthForm::Long { octets: 1 }, &mut buf).is_err());
369 assert!(encode_with(0xFF, LengthForm::Long { octets: 1 }, &mut buf).is_err());
370 assert!(encode_with(0x100, LengthForm::Long { octets: 2 }, &mut buf).is_err());
371 assert!(encode_with(0xFFFF, LengthForm::Long { octets: 2 }, &mut buf).is_err());
372 assert!(encode_with(0x7F, LengthForm::Long { octets: 1 }, &mut buf).is_ok());
374 assert!(encode_with(0x80, LengthForm::Long { octets: 2 }, &mut buf).is_ok());
375 assert!(encode_with(0x100, LengthForm::Long { octets: 3 }, &mut buf).is_ok());
376 assert!(encode_with(5, LengthForm::Long { octets: 0 }, &mut buf).is_err());
377 assert!(encode_with(5, LengthForm::Long { octets: 5 }, &mut buf).is_err());
378 assert!(encode_with(0x1_0000, LengthForm::Long { octets: 4 }, &mut buf).is_err());
379 }
380
381 #[test]
382 fn rejects_a_value_above_the_spec_cap() {
383 assert!(matches!(
385 decode_form(&[0x83, 0x01, 0x00, 0x00]),
386 Err(Error::LengthTooLarge(0x1_0000))
387 ));
388 }
389
390 #[test]
391 fn mutating_a_byte_changes_decode() {
392 let mut buf = [0u8; 4];
393 encode_into(0x1234, &mut buf).unwrap();
394 let (a, _) = decode(&buf).unwrap();
395 buf[2] ^= 0xFF;
396 let (b, _) = decode(&buf).unwrap();
397 assert_ne!(a, b);
398 }
399}