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