Skip to main content

dvb_si/descriptors/ait/
application_usage.rs

1//! Application Usage Descriptor — ETSI TS 102 809 §5.3.5.5, Table 23
2//! (AIT tag 0x16).
3//!
4//! Carried in the AIT common descriptor loop. Indicates the application's
5//! usage type — Table 11 defines known values (e.g. 0x01 = Digital Text).
6
7use crate::descriptors::descriptor_body;
8use crate::error::{Error, Result};
9use dvb_common::{Parse, Serialize};
10
11/// Descriptor tag for application_usage_descriptor (AIT namespace).
12pub const TAG: u8 = 0x16;
13const HEADER_LEN: usize = 2;
14
15/// Known `usage_type` values — ETSI TS 102 809 §5.2.11.1.1 Table 11.
16pub const USAGE_TYPE_DIGITAL_TEXT: u8 = 0x01;
17
18/// Application Usage Descriptor (AIT tag 0x16).
19#[derive(Debug, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize))]
21pub struct ApplicationUsageDescriptor {
22    /// 8-bit usage_type (Table 11: 0x01 = Digital Text, 0x02..0x7F reserved,
23    /// 0x80..0xFF platform-specific).
24    pub usage_type: u8,
25}
26
27impl ApplicationUsageDescriptor {
28    /// Returns the well-known name for `usage_type`, or `None` if the value
29    /// is not recognised.
30    #[must_use]
31    pub fn usage_type_name(&self) -> Option<&'static str> {
32        match self.usage_type {
33            USAGE_TYPE_DIGITAL_TEXT => Some("Digital Text"),
34            _ => None,
35        }
36    }
37}
38
39impl<'a> Parse<'a> for ApplicationUsageDescriptor {
40    type Error = crate::error::Error;
41    fn parse(bytes: &'a [u8]) -> Result<Self> {
42        let body = descriptor_body(
43            bytes,
44            TAG,
45            "ApplicationUsageDescriptor",
46            "unexpected tag for application_usage_descriptor",
47        )?;
48        if body.is_empty() {
49            return Err(Error::InvalidDescriptor {
50                tag: TAG,
51                reason: "application_usage_descriptor body shorter than minimum 1 byte",
52            });
53        }
54        Ok(Self {
55            usage_type: body[0],
56        })
57    }
58}
59
60impl Serialize for ApplicationUsageDescriptor {
61    type Error = crate::error::Error;
62    fn serialized_len(&self) -> usize {
63        HEADER_LEN + 1
64    }
65
66    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
67        let len = self.serialized_len();
68        if buf.len() < len {
69            return Err(Error::OutputBufferTooSmall {
70                need: len,
71                have: buf.len(),
72            });
73        }
74        buf[0] = TAG;
75        buf[1] = 1;
76        buf[2] = self.usage_type;
77        Ok(len)
78    }
79}
80
81impl<'a> crate::traits::DescriptorDef<'a> for ApplicationUsageDescriptor {
82    const TAG: u8 = TAG;
83    const NAME: &'static str = "APPLICATION_USAGE";
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn parse_digital_text() {
92        let bytes = [TAG, 1, USAGE_TYPE_DIGITAL_TEXT];
93        let d = ApplicationUsageDescriptor::parse(&bytes).unwrap();
94        assert_eq!(d.usage_type, USAGE_TYPE_DIGITAL_TEXT);
95        assert_eq!(d.usage_type_name(), Some("Digital Text"));
96    }
97
98    #[test]
99    fn parse_platform_specific() {
100        let bytes = [TAG, 1, 0x80];
101        let d = ApplicationUsageDescriptor::parse(&bytes).unwrap();
102        assert_eq!(d.usage_type, 0x80);
103        assert_eq!(d.usage_type_name(), None);
104    }
105
106    #[test]
107    fn serialize_round_trip() {
108        let d = ApplicationUsageDescriptor {
109            usage_type: USAGE_TYPE_DIGITAL_TEXT,
110        };
111        let mut buf = vec![0u8; d.serialized_len()];
112        d.serialize_into(&mut buf).unwrap();
113        let re = ApplicationUsageDescriptor::parse(&buf).unwrap();
114        assert_eq!(d, re);
115    }
116
117    #[test]
118    fn serialize_byte_identical() {
119        let bytes = [TAG, 1, 0x01];
120        let d = ApplicationUsageDescriptor::parse(&bytes).unwrap();
121        let mut buf = vec![0u8; d.serialized_len()];
122        d.serialize_into(&mut buf).unwrap();
123        assert_eq!(buf.as_slice(), &bytes[..]);
124    }
125}