Skip to main content

dvb_si/descriptors/ait/
external_application_authorisation.rs

1//! External Application Authorisation Descriptor — ETSI TS 102 809 §5.3.5.7, Table 26
2//! (AIT tag 0x05).
3//!
4//! Carried in the AIT common descriptor loop. Authorises external applications
5//! by their application identifier + priority.
6
7use crate::descriptors::descriptor_body;
8use crate::error::{Error, Result};
9use crate::tables::ait::ApplicationIdentifier;
10use alloc::vec::Vec;
11use broadcast_common::{Parse, Serialize};
12
13/// Descriptor tag for external_application_authorisation_descriptor (AIT namespace).
14pub const TAG: u8 = 0x05;
15const HEADER_LEN: usize = 2;
16const ENTRY_LEN: usize = 7;
17
18/// One external application authorisation entry.
19#[derive(Debug, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize))]
21pub struct ExternalAppEntry {
22    /// Application identifier (organisation_id + application_id).
23    pub identifier: ApplicationIdentifier,
24    /// Application priority.
25    pub application_priority: u8,
26}
27
28/// External Application Authorisation Descriptor (AIT tag 0x05).
29#[derive(Debug, Clone, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize))]
31pub struct ExternalApplicationAuthorisationDescriptor {
32    /// Authorised external applications in wire order.
33    pub entries: Vec<ExternalAppEntry>,
34}
35
36impl<'a> Parse<'a> for ExternalApplicationAuthorisationDescriptor {
37    type Error = crate::error::Error;
38    fn parse(bytes: &'a [u8]) -> Result<Self> {
39        let body = descriptor_body(
40            bytes,
41            TAG,
42            "ExternalApplicationAuthorisationDescriptor",
43            "unexpected tag for external_application_authorisation_descriptor",
44        )?;
45        if body.len() % ENTRY_LEN != 0 {
46            return Err(Error::InvalidDescriptor {
47                tag: TAG,
48                reason: "external_application_authorisation_descriptor length must be a multiple of 7",
49            });
50        }
51        let mut entries = Vec::with_capacity(body.len() / ENTRY_LEN);
52        for chunk in body.chunks_exact(ENTRY_LEN) {
53            let (org_bytes, rest) = chunk.split_first_chunk::<4>().unwrap();
54            let organisation_id = u32::from_be_bytes(*org_bytes);
55            let (app_bytes, priority_slice) = rest.split_first_chunk::<2>().unwrap();
56            let application_id = u16::from_be_bytes(*app_bytes);
57            let application_priority = priority_slice[0];
58            entries.push(ExternalAppEntry {
59                identifier: ApplicationIdentifier {
60                    organisation_id,
61                    application_id,
62                },
63                application_priority,
64            });
65        }
66        Ok(Self { entries })
67    }
68}
69
70impl Serialize for ExternalApplicationAuthorisationDescriptor {
71    type Error = crate::error::Error;
72    fn serialized_len(&self) -> usize {
73        HEADER_LEN + self.entries.len() * ENTRY_LEN
74    }
75
76    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
77        if self.entries.len() * ENTRY_LEN > u8::MAX as usize {
78            return Err(Error::InvalidDescriptor {
79                tag: TAG,
80                reason: "external_application_authorisation_descriptor body exceeds 255 bytes",
81            });
82        }
83        let len = self.serialized_len();
84        if buf.len() < len {
85            return Err(Error::OutputBufferTooSmall {
86                need: len,
87                have: buf.len(),
88            });
89        }
90        buf[0] = TAG;
91        buf[1] = (self.entries.len() * ENTRY_LEN) as u8;
92        let mut pos = HEADER_LEN;
93        for e in &self.entries {
94            buf[pos..pos + 4].copy_from_slice(&e.identifier.organisation_id.to_be_bytes());
95            buf[pos + 4..pos + 6].copy_from_slice(&e.identifier.application_id.to_be_bytes());
96            buf[pos + 6] = e.application_priority;
97            pos += ENTRY_LEN;
98        }
99        Ok(len)
100    }
101}
102
103impl crate::traits::DescriptorDef<'_> for ExternalApplicationAuthorisationDescriptor {
104    const TAG: u8 = TAG;
105    const NAME: &'static str = "EXTERNAL_APPLICATION_AUTHORISATION";
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn parse_single_entry() {
114        let bytes = [
115            TAG, 7, 0x00, 0x00, 0x00, 0x01, // organisation_id=1
116            0x00, 0x0A, // application_id=10
117            0x05, // priority=5
118        ];
119        let d = ExternalApplicationAuthorisationDescriptor::parse(&bytes).unwrap();
120        assert_eq!(d.entries.len(), 1);
121        assert_eq!(d.entries[0].identifier.organisation_id, 1);
122        assert_eq!(d.entries[0].identifier.application_id, 10);
123        assert_eq!(d.entries[0].application_priority, 5);
124    }
125
126    #[test]
127    fn parse_multiple_entries() {
128        let bytes = [
129            TAG, 14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x14,
130            0x0A,
131        ];
132        let d = ExternalApplicationAuthorisationDescriptor::parse(&bytes).unwrap();
133        assert_eq!(d.entries.len(), 2);
134        assert_eq!(d.entries[1].identifier.organisation_id, 2);
135    }
136
137    #[test]
138    fn parse_rejects_bad_length() {
139        let bytes = [TAG, 8, 0, 0, 0, 1, 0, 5, 0, 0]; // body not a multiple of 7
140        assert!(ExternalApplicationAuthorisationDescriptor::parse(&bytes).is_err());
141    }
142
143    #[test]
144    fn serialize_round_trip() {
145        let d = ExternalApplicationAuthorisationDescriptor {
146            entries: alloc::vec![ExternalAppEntry {
147                identifier: ApplicationIdentifier {
148                    organisation_id: 0xDEAD,
149                    application_id: 0xBEEF,
150                },
151                application_priority: 42,
152            }],
153        };
154        let mut buf = vec![0u8; d.serialized_len()];
155        d.serialize_into(&mut buf).unwrap();
156        let re = ExternalApplicationAuthorisationDescriptor::parse(&buf).unwrap();
157        assert_eq!(d, re);
158    }
159
160    #[test]
161    fn serialize_byte_identical() {
162        let bytes = [TAG, 7, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0xFF];
163        let d = ExternalApplicationAuthorisationDescriptor::parse(&bytes).unwrap();
164        let mut buf = vec![0u8; d.serialized_len()];
165        d.serialize_into(&mut buf).unwrap();
166        assert_eq!(buf.as_slice(), &bytes[..]);
167    }
168}