1use crate::error::{Error, Result};
18use crate::traits::Descriptor;
19use dvb_common::{Parse, Serialize};
20
21pub const TAG: u8 = 0x7B;
23const HEADER_LEN: usize = 2;
24const FIXED_LEN: usize = 5;
26
27const SAMPLE_RATE_CODE_MAX: u8 = 0x0F; const BIT_RATE_CODE_MAX: u8 = 0x3F; const NBLKS_MAX: u8 = 0x7F; const FSIZE_MAX: u16 = 0x3FFF; const SURROUND_MODE_MAX: u8 = 0x3F; const EXTENDED_SURROUND_MAX: u8 = 0x03; #[derive(Debug, Clone, PartialEq, Eq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize))]
37#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
38pub struct DtsDescriptor<'a> {
39 pub sample_rate_code: u8,
41 pub bit_rate_code: u8,
43 pub nblks: u8,
45 pub fsize: u16,
47 pub surround_mode: u8,
49 pub lfe_flag: bool,
51 pub extended_surround_flag: u8,
53 pub additional_info: &'a [u8],
55}
56
57impl<'a> Parse<'a> for DtsDescriptor<'a> {
58 type Error = crate::error::Error;
59 fn parse(bytes: &'a [u8]) -> Result<Self> {
60 if bytes.len() < HEADER_LEN {
61 return Err(Error::BufferTooShort {
62 need: HEADER_LEN,
63 have: bytes.len(),
64 what: "DtsDescriptor header",
65 });
66 }
67 if bytes[0] != TAG {
68 return Err(Error::InvalidDescriptor {
69 tag: bytes[0],
70 reason: "unexpected tag for DTS_descriptor",
71 });
72 }
73 let length = bytes[1] as usize;
74 let end = HEADER_LEN + length;
75 if bytes.len() < end {
76 return Err(Error::BufferTooShort {
77 need: end,
78 have: bytes.len(),
79 what: "DtsDescriptor body",
80 });
81 }
82 if length < FIXED_LEN {
83 return Err(Error::InvalidDescriptor {
84 tag: TAG,
85 reason: "DTS_descriptor body shorter than 5 bytes",
86 });
87 }
88 let body = &bytes[HEADER_LEN..end];
89 let packed: u64 = (u64::from(body[0]) << 32)
91 | (u64::from(body[1]) << 24)
92 | (u64::from(body[2]) << 16)
93 | (u64::from(body[3]) << 8)
94 | u64::from(body[4]);
95 let sample_rate_code = ((packed >> 36) & 0x0F) as u8;
96 let bit_rate_code = ((packed >> 30) & 0x3F) as u8;
97 let nblks = ((packed >> 23) & 0x7F) as u8;
98 let fsize = ((packed >> 9) & 0x3FFF) as u16;
99 let surround_mode = ((packed >> 3) & 0x3F) as u8;
100 let lfe_flag = ((packed >> 2) & 0x01) != 0;
101 let extended_surround_flag = (packed & 0x03) as u8;
102 let additional_info = &body[FIXED_LEN..];
103 Ok(Self {
104 sample_rate_code,
105 bit_rate_code,
106 nblks,
107 fsize,
108 surround_mode,
109 lfe_flag,
110 extended_surround_flag,
111 additional_info,
112 })
113 }
114}
115
116impl Serialize for DtsDescriptor<'_> {
117 type Error = crate::error::Error;
118 fn serialized_len(&self) -> usize {
119 HEADER_LEN + FIXED_LEN + self.additional_info.len()
120 }
121
122 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
123 if self.sample_rate_code > SAMPLE_RATE_CODE_MAX {
124 return Err(Error::InvalidDescriptor {
125 tag: TAG,
126 reason: "sample_rate_code exceeds 4 bits",
127 });
128 }
129 if self.bit_rate_code > BIT_RATE_CODE_MAX {
130 return Err(Error::InvalidDescriptor {
131 tag: TAG,
132 reason: "bit_rate_code exceeds 6 bits",
133 });
134 }
135 if self.nblks > NBLKS_MAX {
136 return Err(Error::InvalidDescriptor {
137 tag: TAG,
138 reason: "nblks exceeds 7 bits",
139 });
140 }
141 if self.fsize > FSIZE_MAX {
142 return Err(Error::InvalidDescriptor {
143 tag: TAG,
144 reason: "fsize exceeds 14 bits",
145 });
146 }
147 if self.surround_mode > SURROUND_MODE_MAX {
148 return Err(Error::InvalidDescriptor {
149 tag: TAG,
150 reason: "surround_mode exceeds 6 bits",
151 });
152 }
153 if self.extended_surround_flag > EXTENDED_SURROUND_MAX {
154 return Err(Error::InvalidDescriptor {
155 tag: TAG,
156 reason: "extended_surround_flag exceeds 2 bits",
157 });
158 }
159 if FIXED_LEN + self.additional_info.len() > u8::MAX as usize {
160 return Err(Error::InvalidDescriptor {
161 tag: TAG,
162 reason: "DTS_descriptor body exceeds 255 bytes",
163 });
164 }
165 let len = self.serialized_len();
166 if buf.len() < len {
167 return Err(Error::OutputBufferTooSmall {
168 need: len,
169 have: buf.len(),
170 });
171 }
172 buf[0] = TAG;
173 buf[1] = (FIXED_LEN + self.additional_info.len()) as u8;
174 let packed: u64 = ((u64::from(self.sample_rate_code) & 0x0F) << 36)
175 | ((u64::from(self.bit_rate_code) & 0x3F) << 30)
176 | ((u64::from(self.nblks) & 0x7F) << 23)
177 | ((u64::from(self.fsize) & 0x3FFF) << 9)
178 | ((u64::from(self.surround_mode) & 0x3F) << 3)
179 | (u64::from(self.lfe_flag) << 2)
180 | (u64::from(self.extended_surround_flag) & 0x03);
181 buf[2] = (packed >> 32) as u8;
182 buf[3] = (packed >> 24) as u8;
183 buf[4] = (packed >> 16) as u8;
184 buf[5] = (packed >> 8) as u8;
185 buf[6] = packed as u8;
186 buf[HEADER_LEN + FIXED_LEN..len].copy_from_slice(self.additional_info);
187 Ok(len)
188 }
189}
190
191impl<'a> Descriptor<'a> for DtsDescriptor<'a> {
192 const TAG: u8 = TAG;
193 fn descriptor_length(&self) -> u8 {
194 (FIXED_LEN + self.additional_info.len()) as u8
195 }
196}
197
198impl<'a> crate::traits::DescriptorDef<'a> for DtsDescriptor<'a> {
199 const TAG: u8 = TAG;
200 const NAME: &'static str = "DTS";
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206
207 #[test]
208 fn parse_no_additional_info() {
209 let d_in = DtsDescriptor {
212 sample_rate_code: 0b1101,
213 bit_rate_code: 0b001010,
214 nblks: 8,
215 fsize: 1024,
216 surround_mode: 0b000010,
217 lfe_flag: true,
218 extended_surround_flag: 0b01,
219 additional_info: &[],
220 };
221 let mut buf = vec![0u8; d_in.serialized_len()];
222 d_in.serialize_into(&mut buf).unwrap();
223 let d = DtsDescriptor::parse(&buf).unwrap();
224 assert_eq!(d, d_in);
225 assert_eq!(buf[1], 5);
226 }
227
228 #[test]
229 fn parse_with_additional_info() {
230 let d_in = DtsDescriptor {
231 sample_rate_code: 0b1000,
232 bit_rate_code: 0b011010,
233 nblks: 127,
234 fsize: 0x3FFF,
235 surround_mode: 0b001001,
236 lfe_flag: false,
237 extended_surround_flag: 0b10,
238 additional_info: &[0xAA, 0xBB, 0xCC],
239 };
240 let mut buf = vec![0u8; d_in.serialized_len()];
241 d_in.serialize_into(&mut buf).unwrap();
242 let d = DtsDescriptor::parse(&buf).unwrap();
243 assert_eq!(d.additional_info, &[0xAA, 0xBB, 0xCC]);
244 assert_eq!(d, d_in);
245 }
246
247 #[test]
248 fn parse_rejects_wrong_tag() {
249 let bytes = [0x7C, 5, 0, 0, 0, 0, 0];
250 assert!(matches!(
251 DtsDescriptor::parse(&bytes).unwrap_err(),
252 Error::InvalidDescriptor { tag: 0x7C, .. }
253 ));
254 }
255
256 #[test]
257 fn parse_rejects_body_too_short() {
258 let bytes = [TAG, 4, 0, 0, 0, 0];
259 assert!(matches!(
260 DtsDescriptor::parse(&bytes).unwrap_err(),
261 Error::InvalidDescriptor { .. }
262 ));
263 }
264
265 #[test]
266 fn parse_rejects_length_overrunning_buffer() {
267 let bytes = [TAG, 5, 0, 0, 0];
268 assert!(matches!(
269 DtsDescriptor::parse(&bytes).unwrap_err(),
270 Error::BufferTooShort { .. }
271 ));
272 }
273
274 #[test]
275 fn serialize_round_trip_max_fields() {
276 let d = DtsDescriptor {
277 sample_rate_code: 0x0F,
278 bit_rate_code: 0x3F,
279 nblks: 0x7F,
280 fsize: 0x3FFF,
281 surround_mode: 0x3F,
282 lfe_flag: true,
283 extended_surround_flag: 0x03,
284 additional_info: &[0x01],
285 };
286 let mut buf = vec![0u8; d.serialized_len()];
287 d.serialize_into(&mut buf).unwrap();
288 assert_eq!(DtsDescriptor::parse(&buf).unwrap(), d);
289 }
290
291 #[test]
292 fn serialize_rejects_fsize_over_range() {
293 let d = DtsDescriptor {
294 sample_rate_code: 0,
295 bit_rate_code: 0,
296 nblks: 0,
297 fsize: 0x4000,
298 surround_mode: 0,
299 lfe_flag: false,
300 extended_surround_flag: 0,
301 additional_info: &[],
302 };
303 let mut buf = vec![0u8; d.serialized_len()];
304 assert!(matches!(
305 d.serialize_into(&mut buf).unwrap_err(),
306 Error::InvalidDescriptor { .. }
307 ));
308 }
309
310 #[test]
311 fn serialize_rejects_bit_rate_code_over_range() {
312 let d = DtsDescriptor {
313 sample_rate_code: 0,
314 bit_rate_code: 0x40,
315 nblks: 0,
316 fsize: 0,
317 surround_mode: 0,
318 lfe_flag: false,
319 extended_surround_flag: 0,
320 additional_info: &[],
321 };
322 let mut buf = vec![0u8; d.serialized_len()];
323 assert!(matches!(
324 d.serialize_into(&mut buf).unwrap_err(),
325 Error::InvalidDescriptor { .. }
326 ));
327 }
328
329 #[cfg(feature = "serde")]
330 #[test]
331 fn serde_serializes_to_stable_json() {
332 let d = DtsDescriptor {
335 sample_rate_code: 0b1101,
336 bit_rate_code: 0b001010,
337 nblks: 16,
338 fsize: 2048,
339 surround_mode: 0b001000,
340 lfe_flag: true,
341 extended_surround_flag: 0b01,
342 additional_info: &[0x99],
343 };
344 let j = serde_json::to_string(&d).unwrap();
345 let _v: serde_json::Value = serde_json::from_str(&j).unwrap();
348 assert!(j.contains("sample_rate_code"));
349 }
350}