1use crate::error::{Error, Result};
16use broadcast_common::len::{need_in, need_out};
17
18pub const SIZE_INDICATOR_MASK: u8 = 0x80;
21
22pub const MAX_LENGTH_OCTETS: u8 = 4;
26
27pub const MAX_LENGTH: usize = 0xFFFF;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize))]
44#[non_exhaustive]
45pub enum LengthForm {
46 #[default]
49 Minimal,
50 Long {
53 octets: u8,
56 },
57}
58
59impl LengthForm {
60 #[must_use]
62 pub fn name(&self) -> &'static str {
63 match self {
64 Self::Minimal => "minimal",
65 Self::Long { .. } => "long",
66 }
67 }
68}
69broadcast_common::impl_spec_display!(LengthForm);
70
71pub fn decode(bytes: &[u8]) -> Result<(usize, usize)> {
77 let (value, hdr, _) = decode_form(bytes)?;
78 Ok((value, hdr))
79}
80
81pub fn decode_form(bytes: &[u8]) -> Result<(usize, usize, LengthForm)> {
90 let first = *bytes
91 .first()
92 .ok_or(Error::InvalidLength("empty length_field"))?;
93 if first & SIZE_INDICATOR_MASK == 0 {
94 return Ok(((first & 0x7F) as usize, 1, LengthForm::Minimal));
96 }
97 let n = (first & 0x7F) as usize;
99 if n == 0 {
100 return Err(Error::InvalidLength("indefinite length form not allowed"));
103 }
104 if n > MAX_LENGTH_OCTETS as usize {
105 return Err(Error::InvalidLength(
106 "length_field_size exceeds 4 length octets",
107 ));
108 }
109 need_in(bytes, 1 + n, "length_field (long form)")?;
110 let mut value = 0usize;
111 for &b in &bytes[1..1 + n] {
112 value = (value << 8) | b as usize;
113 }
114 if value > MAX_LENGTH {
115 return Err(Error::LengthTooLarge(value));
116 }
117 let form = if n == minimal_octets(value) && value >= 0x80 {
121 LengthForm::Minimal
122 } else {
123 LengthForm::Long { octets: n as u8 }
124 };
125 Ok((value, 1 + n, form))
126}
127
128const fn minimal_octets(value: usize) -> usize {
130 if value <= 0xFF { 1 } else { 2 }
131}
132
133#[must_use]
135pub fn encoded_len(value: usize) -> usize {
136 if value < 0x80 {
137 1
138 } else if value <= 0xFF {
139 2
140 } else if value <= 0xFFFF {
141 3
142 } else {
143 4
146 }
147}
148
149#[must_use]
156pub fn encoded_len_with(value: usize, form: LengthForm) -> usize {
157 match form {
158 LengthForm::Minimal => encoded_len(value),
159 LengthForm::Long { octets } => 1 + octets as usize,
160 }
161}
162
163pub fn encode_with(value: usize, form: LengthForm, buf: &mut [u8]) -> Result<usize> {
174 let LengthForm::Long { octets } = form else {
175 return encode_into(value, buf);
176 };
177 if value > MAX_LENGTH {
178 return Err(Error::LengthTooLarge(value));
179 }
180 if octets == 0 || octets > MAX_LENGTH_OCTETS {
181 return Err(Error::InvalidLength("length_field_size must be 1..=4"));
182 }
183 let n = octets as usize;
184 if n < 4 && value >> (8 * n) != 0 {
185 return Err(Error::InvalidLength(
186 "length value does not fit the recorded length_field_size",
187 ));
188 }
189 if value >= 0x80 && n == minimal_octets(value) {
195 return Err(Error::InvalidLength(
196 "Long form with the minimal number of octets is LengthForm::Minimal",
197 ));
198 }
199 let need = 1 + n;
200 need_out(buf, need)?;
201 buf[0] = SIZE_INDICATOR_MASK | octets;
202 for (i, slot) in buf[1..need].iter_mut().enumerate() {
203 let shift = 8 * (n - 1 - i);
204 *slot = (value >> shift) as u8;
205 }
206 Ok(need)
207}
208
209pub fn encode_into(value: usize, buf: &mut [u8]) -> Result<usize> {
214 let need = encoded_len(value);
215 if value > 0xFFFF {
216 return Err(Error::LengthTooLarge(value));
217 }
218 need_out(buf, need)?;
219 if value < 0x80 {
220 buf[0] = value as u8;
221 } else if value <= 0xFF {
222 buf[0] = SIZE_INDICATOR_MASK | 1;
223 buf[1] = value as u8;
224 } else {
225 buf[0] = SIZE_INDICATOR_MASK | 2;
226 buf[1] = (value >> 8) as u8;
227 buf[2] = value as u8;
228 }
229 Ok(need)
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn short_form_round_trip() {
238 for v in [0usize, 1, 0x7F] {
239 let mut buf = [0u8; 4];
240 let n = encode_into(v, &mut buf).unwrap();
241 assert_eq!(n, 1);
242 assert_eq!(encoded_len(v), 1);
243 let (decoded, hdr) = decode(&buf).unwrap();
244 assert_eq!((decoded, hdr), (v, 1));
245 }
246 }
247
248 #[test]
249 fn two_byte_form_round_trip() {
250 for v in [0x80usize, 0xFF] {
251 let mut buf = [0u8; 4];
252 let n = encode_into(v, &mut buf).unwrap();
253 assert_eq!(n, 2);
254 assert_eq!(buf[0], SIZE_INDICATOR_MASK | 1);
255 let (decoded, hdr) = decode(&buf).unwrap();
256 assert_eq!((decoded, hdr), (v, 2));
257 }
258 }
259
260 #[test]
261 fn three_byte_form_round_trip() {
262 for v in [0x100usize, 0x1234, 0xFFFF] {
263 let mut buf = [0u8; 4];
264 let n = encode_into(v, &mut buf).unwrap();
265 assert_eq!(n, 3);
266 assert_eq!(buf[0], SIZE_INDICATOR_MASK | 2);
267 let (decoded, hdr) = decode(&buf).unwrap();
268 assert_eq!((decoded, hdr), (v, 3));
269 }
270 }
271
272 #[test]
273 fn rejects_oversize() {
274 let mut buf = [0u8; 4];
275 assert!(matches!(
276 encode_into(0x1_0000, &mut buf),
277 Err(Error::LengthTooLarge(0x1_0000))
278 ));
279 }
280
281 #[test]
282 fn rejects_indefinite_and_wide() {
283 assert_eq!(
284 decode(&[0x80]),
285 Err(Error::InvalidLength("indefinite length form not allowed"))
286 );
287 assert_eq!(
288 decode(&[0x85, 0, 0, 0, 0, 0]),
289 Err(Error::InvalidLength(
290 "length_field_size exceeds 4 length octets"
291 ))
292 );
293 assert_eq!(decode(&[]), Err(Error::InvalidLength("empty length_field")));
294 assert_eq!(
295 decode(&[0x82, 0x12]),
296 Err(Error::BufferTooShort(
297 broadcast_common::error::BufferTooShort {
298 need: 3,
299 have: 2,
300 what: "length_field (long form)"
301 }
302 ))
303 );
304 }
305
306 #[test]
311 fn every_form_round_trips_byte_exactly() {
312 let cases: &[(&[u8], usize, LengthForm)] = &[
313 (&[0x05], 5, LengthForm::Minimal),
314 (&[0x7F], 127, LengthForm::Minimal),
315 (&[0x81, 0x80], 0x80, LengthForm::Minimal),
316 (&[0x81, 0xFF], 0xFF, LengthForm::Minimal),
317 (&[0x82, 0x01, 0x00], 0x100, LengthForm::Minimal),
318 (&[0x82, 0xFF, 0xFF], 0xFFFF, LengthForm::Minimal),
319 (&[0x81, 0x05], 5, LengthForm::Long { octets: 1 }),
321 (&[0x81, 0x00], 0, LengthForm::Long { octets: 1 }),
322 (&[0x82, 0x00, 0x09], 9, LengthForm::Long { octets: 2 }),
324 (&[0x82, 0x00, 0x80], 0x80, LengthForm::Long { octets: 2 }),
325 (
326 &[0x83, 0x00, 0x01, 0x00],
327 0x100,
328 LengthForm::Long { octets: 3 },
329 ),
330 (&[0x83, 0x00, 0x00, 0x09], 9, LengthForm::Long { octets: 3 }),
331 (
332 &[0x84, 0x00, 0x00, 0x00, 0x09],
333 9,
334 LengthForm::Long { octets: 4 },
335 ),
336 ];
337 for &(wire, value, form) in cases {
338 let (v, hdr, f) = decode_form(wire).unwrap();
339 assert_eq!((v, hdr, f), (value, wire.len(), form), "{wire:02X?}");
340 let mut buf = [0u8; 8];
341 let n = encode_with(value, form, &mut buf).unwrap();
342 assert_eq!(&buf[..n], wire, "re-encode {wire:02X?}");
343 assert_eq!(encoded_len_with(value, form), wire.len());
344 }
345 }
346
347 #[test]
349 fn minimal_form_matches_encode_into() {
350 for v in [0usize, 1, 0x7F, 0x80, 0xFF, 0x100, 0x1234, 0xFFFF] {
351 let (mut a, mut b) = ([0u8; 4], [0u8; 4]);
352 let na = encode_into(v, &mut a).unwrap();
353 let nb = encode_with(v, LengthForm::default(), &mut b).unwrap();
354 assert_eq!(a[..na], b[..nb]);
355 }
356 }
357
358 #[test]
359 fn encode_with_rejects_a_form_that_cannot_hold_the_value() {
360 let mut buf = [0u8; 8];
361 assert_eq!(
363 encode_with(0x100, LengthForm::Long { octets: 1 }, &mut buf),
364 Err(Error::InvalidLength(
365 "length value does not fit the recorded length_field_size"
366 ))
367 );
368 assert_eq!(
370 encode_with(0x80, LengthForm::Long { octets: 1 }, &mut buf),
371 Err(Error::InvalidLength(
372 "Long form with the minimal number of octets is LengthForm::Minimal"
373 ))
374 );
375 assert_eq!(
376 encode_with(0xFF, LengthForm::Long { octets: 1 }, &mut buf),
377 Err(Error::InvalidLength(
378 "Long form with the minimal number of octets is LengthForm::Minimal"
379 ))
380 );
381 assert_eq!(
382 encode_with(0x100, LengthForm::Long { octets: 2 }, &mut buf),
383 Err(Error::InvalidLength(
384 "Long form with the minimal number of octets is LengthForm::Minimal"
385 ))
386 );
387 assert_eq!(
388 encode_with(0xFFFF, LengthForm::Long { octets: 2 }, &mut buf),
389 Err(Error::InvalidLength(
390 "Long form with the minimal number of octets is LengthForm::Minimal"
391 ))
392 );
393 assert!(encode_with(0x7F, LengthForm::Long { octets: 1 }, &mut buf).is_ok());
395 assert!(encode_with(0x80, LengthForm::Long { octets: 2 }, &mut buf).is_ok());
396 assert!(encode_with(0x100, LengthForm::Long { octets: 3 }, &mut buf).is_ok());
397 assert_eq!(
398 encode_with(5, LengthForm::Long { octets: 0 }, &mut buf),
399 Err(Error::InvalidLength("length_field_size must be 1..=4"))
400 );
401 assert_eq!(
402 encode_with(5, LengthForm::Long { octets: 5 }, &mut buf),
403 Err(Error::InvalidLength("length_field_size must be 1..=4"))
404 );
405 assert_eq!(
406 encode_with(0x1_0000, LengthForm::Long { octets: 4 }, &mut buf),
407 Err(Error::LengthTooLarge(0x1_0000))
408 );
409 }
410
411 #[test]
412 fn rejects_a_value_above_the_spec_cap() {
413 assert!(matches!(
415 decode_form(&[0x83, 0x01, 0x00, 0x00]),
416 Err(Error::LengthTooLarge(0x1_0000))
417 ));
418 }
419
420 #[test]
421 fn mutating_a_byte_changes_decode() {
422 let mut buf = [0u8; 4];
423 encode_into(0x1234, &mut buf).unwrap();
424 let (a, _) = decode(&buf).unwrap();
425 buf[2] ^= 0xFF;
426 let (b, _) = decode(&buf).unwrap();
427 assert_ne!(a, b);
428 }
429}