dvb_si/descriptors/ait/
application_name.rs1use crate::descriptors::descriptor_body;
9use crate::error::{Error, Result};
10use crate::text::{DvbText, LangCode};
11use alloc::vec::Vec;
12use dvb_common::{Parse, Serialize};
13
14pub const TAG: u8 = 0x01;
16const HEADER_LEN: usize = 2;
17const LANG_LEN: usize = 3;
18const NAME_LEN_FIELD: usize = 1;
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize))]
23#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
24pub struct ApplicationNameEntry<'a> {
25 pub language_code: LangCode,
27 pub application_name: DvbText<'a>,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize))]
34#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
35pub struct ApplicationNameDescriptor<'a> {
36 pub entries: Vec<ApplicationNameEntry<'a>>,
38}
39
40impl<'a> Parse<'a> for ApplicationNameDescriptor<'a> {
41 type Error = crate::error::Error;
42 fn parse(bytes: &'a [u8]) -> Result<Self> {
43 let body = descriptor_body(
44 bytes,
45 TAG,
46 "ApplicationNameDescriptor",
47 "unexpected tag for application_name_descriptor",
48 )?;
49 let mut entries = Vec::new();
50 let mut pos = 0;
51 while pos < body.len() {
52 if pos + LANG_LEN + NAME_LEN_FIELD > body.len() {
53 return Err(Error::InvalidDescriptor {
54 tag: TAG,
55 reason: "entry header runs past descriptor end",
56 });
57 }
58 let language_code = LangCode([body[pos], body[pos + 1], body[pos + 2]]);
59 let name_len = body[pos + LANG_LEN] as usize;
60 let name_start = pos + LANG_LEN + NAME_LEN_FIELD;
61 let name_end = name_start + name_len;
62 if name_end > body.len() {
63 return Err(Error::InvalidDescriptor {
64 tag: TAG,
65 reason: "application_name_length runs past descriptor end",
66 });
67 }
68 entries.push(ApplicationNameEntry {
69 language_code,
70 application_name: DvbText::new(&body[name_start..name_end]),
71 });
72 pos = name_end;
73 }
74 Ok(Self { entries })
75 }
76}
77
78impl Serialize for ApplicationNameDescriptor<'_> {
79 type Error = crate::error::Error;
80 fn serialized_len(&self) -> usize {
81 HEADER_LEN
82 + self
83 .entries
84 .iter()
85 .map(|e| LANG_LEN + NAME_LEN_FIELD + e.application_name.len())
86 .sum::<usize>()
87 }
88
89 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
90 for e in &self.entries {
91 if e.application_name.len() > u8::MAX as usize {
92 return Err(Error::InvalidDescriptor {
93 tag: TAG,
94 reason: "application_name exceeds 255 bytes",
95 });
96 }
97 }
98 let len = self.serialized_len();
99 let body_len = len - HEADER_LEN;
100 if body_len > u8::MAX as usize {
101 return Err(Error::InvalidDescriptor {
102 tag: TAG,
103 reason: "application_name_descriptor body exceeds 255 bytes",
104 });
105 }
106 if buf.len() < len {
107 return Err(Error::OutputBufferTooSmall {
108 need: len,
109 have: buf.len(),
110 });
111 }
112 buf[0] = TAG;
113 buf[1] = body_len as u8;
114 let mut pos = HEADER_LEN;
115 for e in &self.entries {
116 buf[pos..pos + LANG_LEN].copy_from_slice(&e.language_code.0);
117 buf[pos + LANG_LEN] = e.application_name.len() as u8;
118 let name_start = pos + LANG_LEN + NAME_LEN_FIELD;
119 buf[name_start..name_start + e.application_name.len()]
120 .copy_from_slice(e.application_name.raw());
121 pos = name_start + e.application_name.len();
122 }
123 Ok(len)
124 }
125}
126
127impl<'a> crate::traits::DescriptorDef<'a> for ApplicationNameDescriptor<'a> {
128 const TAG: u8 = TAG;
129 const NAME: &'static str = "APPLICATION_NAME";
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 fn build_single_entry_foo() -> [u8; 9] {
138 [TAG, 7, b'e', b'n', b'g', 3, b'F', b'o', b'o']
139 }
140
141 fn build_two_entries() -> [u8; 16] {
143 [
144 TAG, 14, b'e', b'n', b'g', 3, b'F', b'o', b'o', b'f', b'r', b'a', 3, b'B', b'a', b'r',
145 ]
146 }
147
148 #[test]
149 fn parse_single_entry() {
150 let bytes = build_single_entry_foo();
151 let d = ApplicationNameDescriptor::parse(&bytes).unwrap();
152 assert_eq!(d.entries.len(), 1);
153 assert_eq!(d.entries[0].language_code, LangCode(*b"eng"));
154 assert_eq!(d.entries[0].application_name.raw(), b"Foo");
155 }
156
157 #[test]
158 fn parse_multiple_entries() {
159 let bytes = build_two_entries();
160 let d = ApplicationNameDescriptor::parse(&bytes).unwrap();
161 assert_eq!(d.entries.len(), 2);
162 assert_eq!(d.entries[0].language_code, LangCode(*b"eng"));
163 assert_eq!(d.entries[1].language_code, LangCode(*b"fra"));
164 }
165
166 #[test]
167 fn serialize_round_trip() {
168 let d = ApplicationNameDescriptor {
169 entries: alloc::vec![
170 ApplicationNameEntry {
171 language_code: LangCode(*b"eng"),
172 application_name: DvbText::new(b"HbbTV"),
173 },
174 ApplicationNameEntry {
175 language_code: LangCode(*b"deu"),
176 application_name: DvbText::new(b"App"),
177 },
178 ],
179 };
180 let mut buf = vec![0u8; d.serialized_len()];
181 d.serialize_into(&mut buf).unwrap();
182 let re = ApplicationNameDescriptor::parse(&buf).unwrap();
183 assert_eq!(d, re);
184 }
185
186 #[test]
187 fn serialize_byte_identical_single() {
188 let bytes = build_single_entry_foo();
189 let d = ApplicationNameDescriptor::parse(&bytes).unwrap();
190 let mut buf = vec![0u8; d.serialized_len()];
191 d.serialize_into(&mut buf).unwrap();
192 assert_eq!(buf.as_slice(), &bytes[..]);
193 }
194
195 #[test]
196 fn serialize_byte_identical_two() {
197 let bytes = build_two_entries();
198 let d = ApplicationNameDescriptor::parse(&bytes).unwrap();
199 let mut buf = vec![0u8; d.serialized_len()];
200 d.serialize_into(&mut buf).unwrap();
201 assert_eq!(buf.as_slice(), &bytes[..]);
202 }
203}