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