Skip to main content

dvb_ci/
length.rs

1//! The EN 50221 `length_field` — the ASN.1-style length used by every PDU at
2//! the Transport, Session and Application layers — ETSI EN 50221 §7, Table 1
3//! (PDF p. 11).
4//!
5//! Coding:
6//! - the first (MSB) bit is the `size_indicator`;
7//! - `size_indicator == 0`: the data-field length is the remaining 7 bits — any
8//!   length `0..=127` fits in one byte;
9//! - `size_indicator == 1`: the remaining 7 bits (`length_field_size`) code how
10//!   many subsequent bytes carry the length, MSB-first. The spec caps any length
11//!   at 65535, i.e. at most three length bytes.
12//!
13//! The indefinite-length ASN.1 form is NOT used.
14
15use crate::error::{Error, Result};
16
17/// The `size_indicator` bit (the MSB of the first `length_field` byte): set when
18/// the field is the multi-byte form.
19pub const SIZE_INDICATOR_MASK: u8 = 0x80;
20
21/// Decode a `length_field` from the front of `bytes`.
22///
23/// Returns `(length_value, header_len)` where `header_len` is the number of
24/// bytes the `length_field` itself occupied (so the body starts at
25/// `bytes[header_len..]`).
26pub 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        // Short form: 7-bit length in this byte.
32        return Ok(((first & 0x7F) as usize, 1));
33    }
34    // Long form: low 7 bits = number of subsequent length bytes.
35    let n = (first & 0x7F) as usize;
36    if n == 0 {
37        // size_indicator==1 with zero following bytes is the indefinite form,
38        // which the spec forbids.
39        return Err(Error::InvalidLength("indefinite length form not allowed"));
40    }
41    if n > 3 {
42        // Spec caps lengths at 65535 (three bytes); refuse anything wider so the
43        // value cannot overflow a sane buffer expectation.
44        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/// Number of bytes [`encode_into`] will write for `value`.
61#[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        // >65535: caller is expected to reject via encode_into; report the
71        // widest legal form so serialized_len stays an upper bound.
72        4
73    }
74}
75
76/// Encode `value` as a `length_field` into `buf`, returning the bytes written.
77///
78/// Uses the short form for `0..=127`, otherwise the minimal long form. Values
79/// above 65535 are rejected ([`Error::LengthTooLarge`]) per the spec cap.
80pub 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()); // indefinite form
156        assert!(decode(&[0x84, 0, 0, 0, 0]).is_err()); // 4 length bytes
157        assert!(decode(&[]).is_err());
158        assert!(decode(&[0x82, 0x12]).is_err()); // truncated long form
159    }
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}