Skip to main content

dvb_si/descriptors/ait/
simple_application_boundary.rs

1//! Simple Application Boundary Descriptor — ETSI TS 102 809 §5.3.8, Table 35
2//! (AIT tag 0x17).
3//!
4//! Carried in the AIT per-application descriptor loop. A list of boundary
5//! extensions, each a length-prefixed byte string.
6
7use crate::descriptors::descriptor_body;
8use crate::error::{Error, Result};
9use alloc::vec::Vec;
10use dvb_common::{Parse, Serialize};
11
12/// Descriptor tag for simple_application_boundary_descriptor (AIT namespace).
13pub const TAG: u8 = 0x17;
14const HEADER_LEN: usize = 2;
15const COUNT_LEN: usize = 1;
16
17/// Simple Application Boundary Descriptor (AIT tag 0x17).
18#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize))]
20pub struct SimpleApplicationBoundaryDescriptor<'a> {
21    /// Boundary extension byte strings in wire order.
22    #[cfg_attr(feature = "serde", serde(borrow))]
23    pub boundary_extensions: Vec<&'a [u8]>,
24}
25
26impl<'a> Parse<'a> for SimpleApplicationBoundaryDescriptor<'a> {
27    type Error = crate::error::Error;
28    fn parse(bytes: &'a [u8]) -> Result<Self> {
29        let body = descriptor_body(
30            bytes,
31            TAG,
32            "SimpleApplicationBoundaryDescriptor",
33            "unexpected tag for simple_application_boundary_descriptor",
34        )?;
35        if body.is_empty() {
36            return Err(Error::InvalidDescriptor {
37                tag: TAG,
38                reason: "simple_application_boundary_descriptor body is empty",
39            });
40        }
41        let boundary_extension_count = body[0] as usize;
42        let mut extensions = Vec::with_capacity(boundary_extension_count);
43        let mut pos = COUNT_LEN;
44        for _ in 0..boundary_extension_count {
45            if pos >= body.len() {
46                return Err(Error::InvalidDescriptor {
47                    tag: TAG,
48                    reason: "boundary_extension_length missing",
49                });
50            }
51            let ext_len = body[pos] as usize;
52            pos += 1;
53            let ext_end = pos + ext_len;
54            if ext_end > body.len() {
55                return Err(Error::InvalidDescriptor {
56                    tag: TAG,
57                    reason: "boundary_extension bytes run past descriptor end",
58                });
59            }
60            extensions.push(&body[pos..ext_end]);
61            pos = ext_end;
62        }
63        Ok(Self {
64            boundary_extensions: extensions,
65        })
66    }
67}
68
69impl Serialize for SimpleApplicationBoundaryDescriptor<'_> {
70    type Error = crate::error::Error;
71    fn serialized_len(&self) -> usize {
72        HEADER_LEN
73            + COUNT_LEN
74            + self
75                .boundary_extensions
76                .iter()
77                .map(|e| 1 + e.len())
78                .sum::<usize>()
79    }
80
81    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
82        for e in &self.boundary_extensions {
83            if e.len() > u8::MAX as usize {
84                return Err(Error::InvalidDescriptor {
85                    tag: TAG,
86                    reason: "boundary_extension exceeds 255 bytes",
87                });
88            }
89        }
90        let len = self.serialized_len();
91        let body_len = len - HEADER_LEN;
92        if body_len > u8::MAX as usize {
93            return Err(Error::InvalidDescriptor {
94                tag: TAG,
95                reason: "simple_application_boundary_descriptor body exceeds 255 bytes",
96            });
97        }
98        if buf.len() < len {
99            return Err(Error::OutputBufferTooSmall {
100                need: len,
101                have: buf.len(),
102            });
103        }
104        buf[0] = TAG;
105        buf[1] = body_len as u8;
106        buf[2] = self.boundary_extensions.len() as u8;
107        let mut pos = HEADER_LEN + COUNT_LEN;
108        for e in &self.boundary_extensions {
109            buf[pos] = e.len() as u8;
110            buf[pos + 1..pos + 1 + e.len()].copy_from_slice(e);
111            pos += 1 + e.len();
112        }
113        Ok(len)
114    }
115}
116
117impl<'a> crate::traits::DescriptorDef<'a> for SimpleApplicationBoundaryDescriptor<'a> {
118    const TAG: u8 = TAG;
119    const NAME: &'static str = "SIMPLE_APPLICATION_BOUNDARY";
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    /// Body: count(1) + len(1) + "foo"(3) + len(1) + "ba"(2) = 8.
127    fn build_two_extensions() -> [u8; 10] {
128        [
129            TAG, 8, 2, // count
130            3, b'f', b'o', b'o', 2, b'b', b'a',
131        ]
132    }
133
134    #[test]
135    fn parse_two_extensions() {
136        let bytes = build_two_extensions();
137        let d = SimpleApplicationBoundaryDescriptor::parse(&bytes).unwrap();
138        assert_eq!(d.boundary_extensions.len(), 2);
139        assert_eq!(d.boundary_extensions[0], b"foo");
140        assert_eq!(d.boundary_extensions[1], b"ba");
141    }
142
143    #[test]
144    fn parse_no_extensions() {
145        let bytes = [TAG, 1, 0];
146        let d = SimpleApplicationBoundaryDescriptor::parse(&bytes).unwrap();
147        assert!(d.boundary_extensions.is_empty());
148    }
149
150    #[test]
151    fn serialize_round_trip() {
152        let d = SimpleApplicationBoundaryDescriptor {
153            boundary_extensions: alloc::vec![b"abc" as &[u8], b"de" as &[u8]],
154        };
155        let mut buf = vec![0u8; d.serialized_len()];
156        d.serialize_into(&mut buf).unwrap();
157        let re = SimpleApplicationBoundaryDescriptor::parse(&buf).unwrap();
158        assert_eq!(d, re);
159    }
160
161    #[test]
162    fn serialize_byte_identical() {
163        let bytes = build_two_extensions();
164        let d = SimpleApplicationBoundaryDescriptor::parse(&bytes).unwrap();
165        let mut buf = vec![0u8; d.serialized_len()];
166        d.serialize_into(&mut buf).unwrap();
167        assert_eq!(buf.as_slice(), &bytes[..]);
168    }
169}