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