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