1use crate::error::{Error, Result};
16use crate::traits::Descriptor;
17use dvb_common::{Parse, Serialize};
18
19pub const TAG: u8 = 0x7C;
21const HEADER_LEN: usize = 2;
22
23const FLAG_AAC_TYPE: u8 = 0x80;
24const FLAG_SAOC_DE: u8 = 0x40;
25const RESERVED_ZERO_MASK: u8 = 0x3F;
27
28#[derive(Debug, Clone, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize))]
31pub struct AacExtension<'a> {
32 pub saoc_de_flag: bool,
34 pub aac_type: Option<u8>,
37 pub additional_info: &'a [u8],
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize))]
44pub struct AacDescriptor<'a> {
45 pub profile_and_level: u8,
47 pub extension: Option<AacExtension<'a>>,
49}
50
51impl<'a> Parse<'a> for AacDescriptor<'a> {
52 type Error = crate::error::Error;
53 fn parse(bytes: &'a [u8]) -> Result<Self> {
54 if bytes.len() < HEADER_LEN + 1 {
55 return Err(Error::BufferTooShort {
56 need: HEADER_LEN + 1,
57 have: bytes.len(),
58 what: "AacDescriptor header+profile",
59 });
60 }
61 if bytes[0] != TAG {
62 return Err(Error::InvalidDescriptor {
63 tag: bytes[0],
64 reason: "unexpected tag for AAC_descriptor",
65 });
66 }
67 let length = bytes[1] as usize;
68 let end = HEADER_LEN + length;
69 if bytes.len() < end {
70 return Err(Error::BufferTooShort {
71 need: end,
72 have: bytes.len(),
73 what: "AacDescriptor body",
74 });
75 }
76 if length < 1 {
77 return Err(Error::InvalidDescriptor {
78 tag: TAG,
79 reason: "AAC_descriptor body shorter than 1 byte",
80 });
81 }
82 let body = &bytes[HEADER_LEN..end];
83 let profile_and_level = body[0];
84 let extension = if length > 1 {
85 let flags = body[1];
86 let aac_type_flag = (flags & FLAG_AAC_TYPE) != 0;
87 let saoc_de_flag = (flags & FLAG_SAOC_DE) != 0;
88 let mut pos = 2;
89 let aac_type = if aac_type_flag {
90 if pos >= body.len() {
91 return Err(Error::InvalidDescriptor {
92 tag: TAG,
93 reason: "AAC_type_flag set but AAC_type byte missing",
94 });
95 }
96 let t = body[pos];
97 pos += 1;
98 Some(t)
99 } else {
100 None
101 };
102 let additional_info = &body[pos..];
103 Some(AacExtension {
104 saoc_de_flag,
105 aac_type,
106 additional_info,
107 })
108 } else {
109 None
110 };
111 Ok(Self {
112 profile_and_level,
113 extension,
114 })
115 }
116}
117
118impl Serialize for AacDescriptor<'_> {
119 type Error = crate::error::Error;
120 fn serialized_len(&self) -> usize {
121 let body = 1 + match &self.extension {
122 None => 0,
123 Some(ext) => 1 + usize::from(ext.aac_type.is_some()) + ext.additional_info.len(),
124 };
125 HEADER_LEN + body
126 }
127
128 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
129 let body_len = self.serialized_len() - HEADER_LEN;
130 if body_len > u8::MAX as usize {
131 return Err(Error::InvalidDescriptor {
132 tag: TAG,
133 reason: "AAC_descriptor body exceeds 255 bytes",
134 });
135 }
136 let len = self.serialized_len();
137 if buf.len() < len {
138 return Err(Error::OutputBufferTooSmall {
139 need: len,
140 have: buf.len(),
141 });
142 }
143 buf[0] = TAG;
144 buf[1] = body_len as u8;
145 buf[2] = self.profile_and_level;
146 let mut pos = 3;
147 if let Some(ext) = &self.extension {
148 let mut flags = 0u8;
149 if ext.aac_type.is_some() {
150 flags |= FLAG_AAC_TYPE;
151 }
152 if ext.saoc_de_flag {
153 flags |= FLAG_SAOC_DE;
154 }
155 buf[pos] = flags & !RESERVED_ZERO_MASK;
157 pos += 1;
158 if let Some(t) = ext.aac_type {
159 buf[pos] = t;
160 pos += 1;
161 }
162 buf[pos..pos + ext.additional_info.len()].copy_from_slice(ext.additional_info);
163 }
164 Ok(len)
165 }
166}
167
168impl<'a> Descriptor<'a> for AacDescriptor<'a> {
169 const TAG: u8 = TAG;
170 fn descriptor_length(&self) -> u8 {
171 (self.serialized_len() - HEADER_LEN) as u8
172 }
173}
174
175impl<'a> crate::traits::DescriptorDef<'a> for AacDescriptor<'a> {
176 const TAG: u8 = TAG;
177 const NAME: &'static str = "AAC";
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn parse_profile_only() {
186 let bytes = [TAG, 1, 0x50];
187 let d = AacDescriptor::parse(&bytes).unwrap();
188 assert_eq!(d.profile_and_level, 0x50);
189 assert!(d.extension.is_none());
190 }
191
192 #[test]
193 fn parse_with_flags_no_aac_type() {
194 let bytes = [TAG, 2, 0x51, FLAG_SAOC_DE];
196 let d = AacDescriptor::parse(&bytes).unwrap();
197 let ext = d.extension.unwrap();
198 assert!(ext.saoc_de_flag);
199 assert!(ext.aac_type.is_none());
200 assert!(ext.additional_info.is_empty());
201 }
202
203 #[test]
204 fn parse_with_aac_type() {
205 let bytes = [TAG, 3, 0x52, FLAG_AAC_TYPE, 0x03];
206 let d = AacDescriptor::parse(&bytes).unwrap();
207 let ext = d.extension.unwrap();
208 assert!(!ext.saoc_de_flag);
209 assert_eq!(ext.aac_type, Some(0x03));
210 assert!(ext.additional_info.is_empty());
211 }
212
213 #[test]
214 fn parse_with_aac_type_and_additional_info() {
215 let bytes = [TAG, 5, 0x52, FLAG_AAC_TYPE | FLAG_SAOC_DE, 0x05, 0xAA, 0xBB];
216 let d = AacDescriptor::parse(&bytes).unwrap();
217 let ext = d.extension.unwrap();
218 assert!(ext.saoc_de_flag);
219 assert_eq!(ext.aac_type, Some(0x05));
220 assert_eq!(ext.additional_info, &[0xAA, 0xBB]);
221 }
222
223 #[test]
224 fn parse_rejects_wrong_tag() {
225 let bytes = [0x7B, 1, 0x50];
226 assert!(matches!(
227 AacDescriptor::parse(&bytes).unwrap_err(),
228 Error::InvalidDescriptor { tag: 0x7B, .. }
229 ));
230 }
231
232 #[test]
233 fn parse_rejects_aac_type_flag_without_byte() {
234 let bytes = [TAG, 2, 0x50, FLAG_AAC_TYPE];
236 assert!(matches!(
237 AacDescriptor::parse(&bytes).unwrap_err(),
238 Error::InvalidDescriptor { .. }
239 ));
240 }
241
242 #[test]
243 fn parse_rejects_length_overrunning_buffer() {
244 let bytes = [TAG, 4, 0x50];
245 assert!(matches!(
246 AacDescriptor::parse(&bytes).unwrap_err(),
247 Error::BufferTooShort { .. }
248 ));
249 }
250
251 #[test]
252 fn serialize_round_trip_profile_only() {
253 let d = AacDescriptor {
254 profile_and_level: 0x58,
255 extension: None,
256 };
257 let mut buf = vec![0u8; d.serialized_len()];
258 d.serialize_into(&mut buf).unwrap();
259 assert_eq!(buf, vec![TAG, 1, 0x58]);
260 assert_eq!(AacDescriptor::parse(&buf).unwrap(), d);
261 }
262
263 #[test]
264 fn serialize_round_trip_full() {
265 let d = AacDescriptor {
266 profile_and_level: 0x52,
267 extension: Some(AacExtension {
268 saoc_de_flag: true,
269 aac_type: Some(0x40),
270 additional_info: &[0xFE, 0xED],
271 }),
272 };
273 let mut buf = vec![0u8; d.serialized_len()];
274 d.serialize_into(&mut buf).unwrap();
275 assert_eq!(AacDescriptor::parse(&buf).unwrap(), d);
276 }
277
278 #[test]
279 fn serialize_emits_reserved_bits_zero() {
280 let d = AacDescriptor {
281 profile_and_level: 0x50,
282 extension: Some(AacExtension {
283 saoc_de_flag: false,
284 aac_type: None,
285 additional_info: &[],
286 }),
287 };
288 let mut buf = vec![0u8; d.serialized_len()];
289 d.serialize_into(&mut buf).unwrap();
290 assert_eq!(buf[3] & RESERVED_ZERO_MASK, 0);
292 assert_eq!(buf[3], 0x00);
293 }
294
295 #[cfg(feature = "serde")]
296 #[test]
297 fn serde_serializes_to_stable_json() {
298 let d = AacDescriptor {
301 profile_and_level: 0x52,
302 extension: Some(AacExtension {
303 saoc_de_flag: true,
304 aac_type: Some(0x03),
305 additional_info: &[0x11],
306 }),
307 };
308 let j = serde_json::to_string(&d).unwrap();
309 let _v: serde_json::Value = serde_json::from_str(&j).unwrap();
312 assert!(j.contains("profile_and_level"));
313 }
314}