1use super::descriptor_body;
8use crate::descriptors::decoder_config_flags::DecoderConfigFlags;
9use crate::descriptors::metadata_format::MetadataFormat;
10use crate::error::{Error, Result};
11use dvb_common::{Parse, Serialize};
12
13pub const TAG: u8 = 0x26;
15const HEADER_LEN: usize = 2;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize))]
20pub struct DecoderConfigInDescriptor<'a> {
21 #[cfg_attr(feature = "serde", serde(borrow))]
23 pub decoder_config: &'a [u8],
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize))]
29pub struct DecoderConfigDsmcc<'a> {
30 #[cfg_attr(feature = "serde", serde(borrow))]
32 pub dec_config_identification: &'a [u8],
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize))]
38pub struct DecoderConfigOtherService {
39 pub decoder_config_metadata_service_id: u8,
41}
42
43#[derive(Debug, Clone, PartialEq, Eq)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize))]
46pub struct ReservedData<'a> {
47 #[cfg_attr(feature = "serde", serde(borrow))]
49 pub data: &'a [u8],
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize))]
55#[non_exhaustive]
56pub enum DecoderConfig<'a> {
57 None,
59 InDescriptor(DecoderConfigInDescriptor<'a>),
61 SameService,
63 DsmccCarousel(DecoderConfigDsmcc<'a>),
65 OtherService(DecoderConfigOtherService),
67 ReservedData(ReservedData<'a>),
69 Private,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
75#[cfg_attr(feature = "serde", derive(serde::Serialize))]
76#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
77pub struct MetadataDescriptor<'a> {
78 pub metadata_application_format: u16,
80 pub metadata_application_format_identifier: Option<u32>,
82 pub metadata_format: MetadataFormat,
84 pub metadata_format_identifier: Option<u32>,
86 pub metadata_service_id: u8,
88 pub decoder_config_flags: DecoderConfigFlags,
90 pub dsmcc_flag: bool,
92 #[cfg_attr(feature = "serde", serde(borrow))]
94 pub service_identification: Option<&'a [u8]>,
95 pub decoder_config: DecoderConfig<'a>,
97 #[cfg_attr(feature = "serde", serde(borrow))]
99 pub private_data: &'a [u8],
100}
101
102impl<'a> Parse<'a> for MetadataDescriptor<'a> {
103 type Error = crate::error::Error;
104
105 fn parse(bytes: &'a [u8]) -> Result<Self> {
106 let body = descriptor_body(
107 bytes,
108 TAG,
109 "MetadataDescriptor",
110 "unexpected tag for metadata_descriptor",
111 )?;
112
113 if body.len() < 5 {
115 return Err(Error::InvalidDescriptor {
116 tag: TAG,
117 reason: "metadata_descriptor too short (< 5 body bytes)",
118 });
119 }
120
121 let metadata_application_format = u16::from_be_bytes([body[0], body[1]]);
122 let mut pos = 2;
123
124 let metadata_application_format_identifier = if metadata_application_format == 0xFFFF {
125 if body.len() < pos + 4 {
126 return Err(Error::InvalidDescriptor {
127 tag: TAG,
128 reason:
129 "metadata_descriptor too short for metadata_application_format_identifier",
130 });
131 }
132 let id = u32::from_be_bytes([body[pos], body[pos + 1], body[pos + 2], body[pos + 3]]);
133 pos += 4;
134 Some(id)
135 } else {
136 None
137 };
138
139 if body.len() < pos + 1 {
140 return Err(Error::InvalidDescriptor {
141 tag: TAG,
142 reason: "metadata_descriptor too short for metadata_format",
143 });
144 }
145 let metadata_format = MetadataFormat::from_u8(body[pos]);
146 pos += 1;
147
148 let metadata_format_identifier = if body[pos - 1] == 0xFF {
149 if body.len() < pos + 4 {
150 return Err(Error::InvalidDescriptor {
151 tag: TAG,
152 reason: "metadata_descriptor too short for metadata_format_identifier",
153 });
154 }
155 let id = u32::from_be_bytes([body[pos], body[pos + 1], body[pos + 2], body[pos + 3]]);
156 pos += 4;
157 Some(id)
158 } else {
159 None
160 };
161
162 if body.len() < pos + 2 {
163 return Err(Error::InvalidDescriptor {
164 tag: TAG,
165 reason: "metadata_descriptor too short for service_id + flags",
166 });
167 }
168 let metadata_service_id = body[pos];
169 pos += 1;
170
171 let flags = body[pos];
172 let decoder_config_raw = (flags & 0xE0) >> 5;
173 let decoder_config_flags = DecoderConfigFlags::from_u8(decoder_config_raw);
174 let dsmcc_flag = (flags & 0x10) != 0;
175 let _reserved = flags & 0x0F;
176 pos += 1;
177
178 let (service_identification, mut pos) = if dsmcc_flag {
179 if body.len() < pos + 1 {
180 return Err(Error::InvalidDescriptor {
181 tag: TAG,
182 reason: "metadata_descriptor too short for service_identification_length",
183 });
184 }
185 let si_len = body[pos] as usize;
186 pos += 1;
187 if body.len() < pos + si_len {
188 return Err(Error::InvalidDescriptor {
189 tag: TAG,
190 reason: "metadata_descriptor too short for service_identification_record",
191 });
192 }
193 let si = &body[pos..pos + si_len];
194 pos += si_len;
195 (Some(si), pos)
196 } else {
197 (None, pos)
198 };
199
200 let decoder_config = match decoder_config_raw {
201 0 => DecoderConfig::None,
202 1 => {
203 if body.len() < pos + 1 {
204 return Err(Error::InvalidDescriptor {
205 tag: TAG,
206 reason: "metadata_descriptor too short for decoder_config_length",
207 });
208 }
209 let dc_len = body[pos] as usize;
210 pos += 1;
211 if body.len() < pos + dc_len {
212 return Err(Error::InvalidDescriptor {
213 tag: TAG,
214 reason: "metadata_descriptor too short for decoder_config bytes",
215 });
216 }
217 let dc = &body[pos..pos + dc_len];
218 pos += dc_len;
219 DecoderConfig::InDescriptor(DecoderConfigInDescriptor { decoder_config: dc })
220 }
221 2 => DecoderConfig::SameService,
222 3 => {
223 if body.len() < pos + 1 {
224 return Err(Error::InvalidDescriptor {
225 tag: TAG,
226 reason: "metadata_descriptor too short for dec_config_identification_record_length",
227 });
228 }
229 let dci_len = body[pos] as usize;
230 pos += 1;
231 if body.len() < pos + dci_len {
232 return Err(Error::InvalidDescriptor {
233 tag: TAG,
234 reason:
235 "metadata_descriptor too short for dec_config_identification_record",
236 });
237 }
238 let dci = &body[pos..pos + dci_len];
239 pos += dci_len;
240 DecoderConfig::DsmccCarousel(DecoderConfigDsmcc {
241 dec_config_identification: dci,
242 })
243 }
244 4 => {
245 if body.len() < pos + 1 {
246 return Err(Error::InvalidDescriptor {
247 tag: TAG,
248 reason:
249 "metadata_descriptor too short for decoder_config_metadata_service_id",
250 });
251 }
252 let dcm = body[pos];
253 pos += 1;
254 DecoderConfig::OtherService(DecoderConfigOtherService {
255 decoder_config_metadata_service_id: dcm,
256 })
257 }
258 5 | 6 => {
259 if body.len() < pos + 1 {
260 return Err(Error::InvalidDescriptor {
261 tag: TAG,
262 reason: "metadata_descriptor too short for reserved_data_length",
263 });
264 }
265 let rd_len = body[pos] as usize;
266 pos += 1;
267 if body.len() < pos + rd_len {
268 return Err(Error::InvalidDescriptor {
269 tag: TAG,
270 reason: "metadata_descriptor too short for reserved_data",
271 });
272 }
273 let rd = &body[pos..pos + rd_len];
274 pos += rd_len;
275 DecoderConfig::ReservedData(ReservedData { data: rd })
276 }
277 _ => DecoderConfig::Private,
278 };
279
280 let private_data = &body[pos..];
281
282 Ok(Self {
283 metadata_application_format,
284 metadata_application_format_identifier,
285 metadata_format,
286 metadata_format_identifier,
287 metadata_service_id,
288 decoder_config_flags,
289 dsmcc_flag,
290 service_identification,
291 decoder_config,
292 private_data,
293 })
294 }
295}
296
297impl Serialize for MetadataDescriptor<'_> {
298 type Error = crate::error::Error;
299
300 fn serialized_len(&self) -> usize {
301 let mut len: usize = HEADER_LEN + 5; if self.metadata_application_format_identifier.is_some() {
303 len += 4;
304 }
305 if self.metadata_format_identifier.is_some() {
306 len += 4;
307 }
308 if let Some(si) = self.service_identification {
309 len += 1 + si.len();
310 }
311 match &self.decoder_config {
312 DecoderConfig::InDescriptor(d) => len += 1 + d.decoder_config.len(),
313 DecoderConfig::DsmccCarousel(d) => len += 1 + d.dec_config_identification.len(),
314 DecoderConfig::OtherService(_) => len += 1,
315 DecoderConfig::ReservedData(d) => len += 1 + d.data.len(),
316 DecoderConfig::None | DecoderConfig::SameService | DecoderConfig::Private => {}
317 }
318 len += self.private_data.len();
319 len
320 }
321
322 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
323 let len = self.serialized_len();
324 if buf.len() < len {
325 return Err(Error::OutputBufferTooSmall {
326 need: len,
327 have: buf.len(),
328 });
329 }
330 buf[0] = TAG;
331 buf[1] = (len - HEADER_LEN) as u8;
332
333 buf[HEADER_LEN] = (self.metadata_application_format >> 8) as u8;
334 buf[HEADER_LEN + 1] = self.metadata_application_format as u8;
335 let mut pos = HEADER_LEN + 2;
336
337 if let Some(id) = self.metadata_application_format_identifier {
338 buf[pos..pos + 4].copy_from_slice(&id.to_be_bytes());
339 pos += 4;
340 }
341
342 buf[pos] = self.metadata_format.to_u8();
343 pos += 1;
344
345 if let Some(id) = self.metadata_format_identifier {
346 buf[pos..pos + 4].copy_from_slice(&id.to_be_bytes());
347 pos += 4;
348 }
349
350 buf[pos] = self.metadata_service_id;
351 pos += 1;
352
353 let mut flags = (self.decoder_config_flags.to_u8() & 0x07) << 5;
354 if self.dsmcc_flag {
355 flags |= 0x10;
356 }
357 buf[pos] = flags;
358 pos += 1;
359
360 if let Some(si) = self.service_identification {
361 buf[pos] = si.len() as u8;
362 pos += 1;
363 buf[pos..pos + si.len()].copy_from_slice(si);
364 pos += si.len();
365 }
366
367 match &self.decoder_config {
368 DecoderConfig::InDescriptor(d) => {
369 buf[pos] = d.decoder_config.len() as u8;
370 pos += 1;
371 buf[pos..pos + d.decoder_config.len()].copy_from_slice(d.decoder_config);
372 pos += d.decoder_config.len();
373 }
374 DecoderConfig::DsmccCarousel(d) => {
375 buf[pos] = d.dec_config_identification.len() as u8;
376 pos += 1;
377 buf[pos..pos + d.dec_config_identification.len()]
378 .copy_from_slice(d.dec_config_identification);
379 pos += d.dec_config_identification.len();
380 }
381 DecoderConfig::OtherService(d) => {
382 buf[pos] = d.decoder_config_metadata_service_id;
383 pos += 1;
384 }
385 DecoderConfig::ReservedData(d) => {
386 buf[pos] = d.data.len() as u8;
387 pos += 1;
388 buf[pos..pos + d.data.len()].copy_from_slice(d.data);
389 pos += d.data.len();
390 }
391 DecoderConfig::None | DecoderConfig::SameService | DecoderConfig::Private => {}
392 }
393
394 buf[pos..pos + self.private_data.len()].copy_from_slice(self.private_data);
395 Ok(len)
396 }
397}
398
399impl<'a> crate::traits::DescriptorDef<'a> for MetadataDescriptor<'a> {
400 const TAG: u8 = TAG;
401 const NAME: &'static str = "METADATA";
402}
403
404#[cfg(test)]
405mod tests {
406 use super::*;
407
408 fn serialize_round_trip(d: &MetadataDescriptor<'_>) {
409 let mut buf = vec![0u8; d.serialized_len()];
410 let written = d.serialize_into(&mut buf).unwrap();
411 assert_eq!(written, d.serialized_len());
412 let reparsed = MetadataDescriptor::parse(&buf).unwrap();
413 assert_eq!(*d, reparsed, "round-trip mismatch");
414 }
415
416 #[test]
417 fn round_trip_decoder_config_none() {
418 let d = MetadataDescriptor {
419 metadata_application_format: 0x0010,
420 metadata_application_format_identifier: None,
421 metadata_format: MetadataFormat::TeM,
422 metadata_format_identifier: None,
423 metadata_service_id: 5,
424 decoder_config_flags: DecoderConfigFlags::None,
425 dsmcc_flag: false,
426 service_identification: None,
427 decoder_config: DecoderConfig::None,
428 private_data: &[],
429 };
430 serialize_round_trip(&d);
431 }
432
433 #[test]
434 fn round_trip_decoder_config_in_descriptor() {
435 let d = MetadataDescriptor {
436 metadata_application_format: 0x0011,
437 metadata_application_format_identifier: None,
438 metadata_format: MetadataFormat::BiM,
439 metadata_format_identifier: None,
440 metadata_service_id: 3,
441 decoder_config_flags: DecoderConfigFlags::InDescriptor,
442 dsmcc_flag: false,
443 service_identification: None,
444 decoder_config: DecoderConfig::InDescriptor(DecoderConfigInDescriptor {
445 decoder_config: &[0x01, 0x02, 0x03],
446 }),
447 private_data: &[0xFF],
448 };
449 serialize_round_trip(&d);
450 }
451
452 #[test]
453 fn round_trip_decoder_config_same_service() {
454 let d = MetadataDescriptor {
455 metadata_application_format: 0x0100,
456 metadata_application_format_identifier: None,
457 metadata_format: MetadataFormat::AppFormat,
458 metadata_format_identifier: None,
459 metadata_service_id: 1,
460 decoder_config_flags: DecoderConfigFlags::SameService,
461 dsmcc_flag: true,
462 service_identification: Some(&[0xAA, 0xBB]),
463 decoder_config: DecoderConfig::SameService,
464 private_data: &[],
465 };
466 serialize_round_trip(&d);
467 }
468
469 #[test]
470 fn round_trip_decoder_config_dsmcc() {
471 let d = MetadataDescriptor {
472 metadata_application_format: 0x0010,
473 metadata_application_format_identifier: None,
474 metadata_format: MetadataFormat::Reserved1(0x30),
475 metadata_format_identifier: None,
476 metadata_service_id: 7,
477 decoder_config_flags: DecoderConfigFlags::DsmccCarousel,
478 dsmcc_flag: false,
479 service_identification: None,
480 decoder_config: DecoderConfig::DsmccCarousel(DecoderConfigDsmcc {
481 dec_config_identification: &[0x11, 0x22, 0x33, 0x44],
482 }),
483 private_data: &[],
484 };
485 serialize_round_trip(&d);
486 }
487
488 #[test]
489 fn round_trip_decoder_config_other_service() {
490 let d = MetadataDescriptor {
491 metadata_application_format: 0x0010,
492 metadata_application_format_identifier: None,
493 metadata_format: MetadataFormat::Private(0x50),
494 metadata_format_identifier: None,
495 metadata_service_id: 2,
496 decoder_config_flags: DecoderConfigFlags::OtherService,
497 dsmcc_flag: false,
498 service_identification: None,
499 decoder_config: DecoderConfig::OtherService(DecoderConfigOtherService {
500 decoder_config_metadata_service_id: 99,
501 }),
502 private_data: &[],
503 };
504 serialize_round_trip(&d);
505 }
506
507 #[test]
508 fn round_trip_decoder_config_reserved_data() {
509 let d = MetadataDescriptor {
510 metadata_application_format: 0x0010,
511 metadata_application_format_identifier: None,
512 metadata_format: MetadataFormat::Identifier,
513 metadata_format_identifier: Some(0xDEADBEEF),
514 metadata_service_id: 4,
515 decoder_config_flags: DecoderConfigFlags::Reserved(5),
516 dsmcc_flag: false,
517 service_identification: None,
518 decoder_config: DecoderConfig::ReservedData(ReservedData {
519 data: &[0x99, 0x88, 0x77],
520 }),
521 private_data: &[],
522 };
523 serialize_round_trip(&d);
524 }
525
526 #[test]
527 fn round_trip_decoder_config_private() {
528 let d = MetadataDescriptor {
529 metadata_application_format: 0x0010,
530 metadata_application_format_identifier: None,
531 metadata_format: MetadataFormat::TeM,
532 metadata_format_identifier: None,
533 metadata_service_id: 6,
534 decoder_config_flags: DecoderConfigFlags::Private,
535 dsmcc_flag: false,
536 service_identification: None,
537 decoder_config: DecoderConfig::Private,
538 private_data: &[0x01],
539 };
540 serialize_round_trip(&d);
541 }
542
543 #[test]
544 fn round_trip_with_ffff_and_ff() {
545 let d = MetadataDescriptor {
546 metadata_application_format: 0xFFFF,
547 metadata_application_format_identifier: Some(0x11223344),
548 metadata_format: MetadataFormat::Identifier,
549 metadata_format_identifier: Some(0x55667788),
550 metadata_service_id: 8,
551 decoder_config_flags: DecoderConfigFlags::None,
552 dsmcc_flag: true,
553 service_identification: Some(&[0xCA, 0xFE]),
554 decoder_config: DecoderConfig::None,
555 private_data: &[],
556 };
557 serialize_round_trip(&d);
558 }
559
560 #[test]
561 fn parse_rejects_wrong_tag() {
562 let err = MetadataDescriptor::parse(&[0x02, 5, 0, 0, 0, 0, 0]).unwrap_err();
563 assert!(matches!(err, Error::InvalidDescriptor { tag: 0x02, .. }));
564 }
565
566 #[test]
567 fn parse_rejects_too_short() {
568 let err = MetadataDescriptor::parse(&[TAG, 0]).unwrap_err();
569 assert!(matches!(err, Error::InvalidDescriptor { tag: TAG, .. }));
570 }
571}