1use alloc::boxed::Box;
69use alloc::collections::BTreeMap;
70
71use crate::descriptors::any::AnyDescriptor;
72use crate::descriptors::private_data_specifier::PDS_NORDIG;
73
74broadcast_common::declare_object_trait! {
75 pub trait DescriptorObject, "descriptor"
83}
84
85pub(crate) type CustomParse =
92 Box<dyn for<'a> Fn(&'a [u8]) -> crate::Result<Box<dyn DescriptorObject>> + Send + Sync>;
93
94#[derive(Default)]
124pub struct DescriptorRegistry {
125 custom: BTreeMap<(Option<u32>, u8), CustomParse>,
126 logical_channel: bool,
127 logical_channel_pds: alloc::collections::BTreeSet<u32>,
128}
129
130impl DescriptorRegistry {
131 #[must_use]
133 pub fn new() -> Self {
134 Self::default()
135 }
136
137 pub fn register<T>(&mut self) -> &mut Self
158 where
159 T: for<'a> crate::traits::DescriptorDef<'a> + DescriptorObject + 'static,
160 {
161 let tag = <T as crate::traits::DescriptorDef<'static>>::TAG;
162 self.custom.insert(
163 (None, tag),
164 Box::new(|b| {
165 Ok(Box::new(<T as broadcast_common::Parse>::parse(b)?)
166 as Box<dyn DescriptorObject>)
167 }),
168 );
169 self
170 }
171
172 pub fn register_for_pds<T>(&mut self, pds: u32) -> &mut Self
184 where
185 T: for<'a> crate::traits::DescriptorDef<'a> + DescriptorObject + 'static,
186 {
187 let tag = <T as crate::traits::DescriptorDef<'static>>::TAG;
188 self.custom.insert(
189 (Some(pds), tag),
190 Box::new(|b| {
191 Ok(Box::new(<T as broadcast_common::Parse>::parse(b)?)
192 as Box<dyn DescriptorObject>)
193 }),
194 );
195 self
196 }
197
198 pub fn with_logical_channel(&mut self) -> &mut Self {
204 self.logical_channel = true;
205 self
206 }
207
208 pub fn with_logical_channel_for_pds(&mut self, pds: u32) -> &mut Self {
220 self.logical_channel_pds.insert(pds);
221 self
222 }
223
224 pub fn with_nordig_lcn(&mut self) -> &mut Self {
228 self.register_for_pds::<crate::descriptors::nordig::NordigLogicalChannelV1>(PDS_NORDIG);
229 self.register_for_pds::<crate::descriptors::nordig::NordigLogicalChannelV2>(PDS_NORDIG);
230 self
231 }
232
233 pub fn with_avs3_audio(&mut self) -> &mut Self {
239 self.register_for_pds::<crate::descriptors::avs3_audio::Avs3AudioDescriptor>(
240 crate::descriptors::PDS_AVSA,
241 );
242 self
243 }
244
245 pub fn with_avs3_video(&mut self) -> &mut Self {
252 self.register_for_pds::<crate::descriptors::avs3_video::Avs3VideoDescriptor>(
253 crate::descriptors::PDS_AVSV,
254 );
255 self
256 }
257
258 pub fn with_avs2_video(&mut self) -> &mut Self {
263 self.register_for_pds::<crate::descriptors::avs2_video::Avs2VideoDescriptor>(
264 crate::descriptors::PDS_AVSV,
265 );
266 self
267 }
268
269 pub fn with_avs2_audio(&mut self) -> &mut Self {
273 self.register_for_pds::<crate::descriptors::avs2_audio::Avs2AudioDescriptor>(
274 crate::descriptors::PDS_AVSA,
275 );
276 self
277 }
278
279 pub fn with_tuwa_avs3_video(&mut self) -> &mut Self {
283 self.register::<crate::descriptors::tuwa_avs3_video::TuwaAvs3VideoDescriptor>()
284 }
285
286 pub fn with_china_caption_service(&mut self) -> &mut Self {
292 self.register::<crate::descriptors::china_caption_service::ChinaCaptionServiceDescriptor>()
293 }
294
295 pub fn with_atsc_caption_service(&mut self) -> &mut Self {
300 self.register::<crate::descriptors::atsc_caption_service::AtscCaptionServiceDescriptor>()
301 }
302
303 #[must_use]
313 pub fn parse_loop<'r, 'a>(&'r self, bytes: &'a [u8]) -> RegistryIter<'r, 'a> {
314 RegistryIter {
315 registry: self,
316 bytes,
317 pos: 0,
318 fused: false,
319 current_pds: None,
320 }
321 }
322
323 #[must_use]
337 pub fn parse_loop_in_scope<'r, 'a>(
338 &'r self,
339 bytes: &'a [u8],
340 inherited: Option<u32>,
341 ) -> RegistryIter<'r, 'a> {
342 RegistryIter {
343 registry: self,
344 bytes,
345 pos: 0,
346 fused: false,
347 current_pds: inherited,
348 }
349 }
350}
351
352pub struct RegistryIter<'r, 'a> {
360 registry: &'r DescriptorRegistry,
361 bytes: &'a [u8],
362 pos: usize,
363 fused: bool,
364 current_pds: Option<u32>,
365}
366
367pub(crate) fn dispatch_entry<'a>(
373 registry: &DescriptorRegistry,
374 current_pds: Option<u32>,
375 tag: u8,
376 full: &'a [u8],
377) -> crate::Result<AnyDescriptor<'a>> {
378 if let Some(pds) = current_pds
379 && let Some(parse_fn) = registry.custom.get(&(Some(pds), tag))
380 {
381 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
382 }
383 if let Some(parse_fn) = registry.custom.get(&(None, tag)) {
384 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
385 }
386 if let Some(pds) = current_pds
387 && tag == crate::descriptors::logical_channel::TAG
388 && registry.logical_channel_pds.contains(&pds)
389 {
390 use broadcast_common::Parse;
391 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
392 .map(AnyDescriptor::LogicalChannel);
393 }
394 if registry.logical_channel && tag == crate::descriptors::logical_channel::TAG {
395 use broadcast_common::Parse;
396 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
397 .map(AnyDescriptor::LogicalChannel);
398 }
399 if let Some(res) = AnyDescriptor::dispatch(tag, full) {
400 return res;
401 }
402 Ok(AnyDescriptor::Unknown {
403 tag,
404 body: &full[2..],
405 })
406}
407
408fn update_pds(current: &mut Option<u32>, tag: u8, full: &[u8]) {
409 if tag == crate::descriptors::registration::TAG {
415 use broadcast_common::Parse;
416 if let Ok(reg) = crate::descriptors::registration::RegistrationDescriptor::parse(full) {
417 let id = u32::from_be_bytes(reg.format_identifier);
418 if id == crate::descriptors::PDS_AVSA || id == crate::descriptors::PDS_AVSV {
419 *current = Some(id);
420 }
421 }
422 }
423 if tag == crate::descriptors::private_data_specifier::TAG {
424 use broadcast_common::Parse;
425 if let Ok(pds) =
426 crate::descriptors::private_data_specifier::PrivateDataSpecifierDescriptor::parse(full)
427 {
428 *current = Some(pds.private_data_specifier);
429 }
430 }
431}
432
433impl RegistryIter<'_, '_> {
434 #[must_use]
440 pub fn avs_scope(&self) -> Option<u32> {
441 self.current_pds
442 .filter(|p| *p == crate::descriptors::PDS_AVSA || *p == crate::descriptors::PDS_AVSV)
443 }
444}
445
446impl<'a> Iterator for RegistryIter<'_, 'a> {
447 type Item = crate::Result<AnyDescriptor<'a>>;
448
449 fn next(&mut self) -> Option<Self::Item> {
450 let (tag, full) = match crate::descriptors::any::next_loop_entry(
451 self.bytes,
452 &mut self.pos,
453 &mut self.fused,
454 )? {
455 Ok(v) => v,
456 Err(e) => return Some(Err(e)),
457 };
458
459 update_pds(&mut self.current_pds, tag, full);
460
461 Some(dispatch_entry(self.registry, self.current_pds, tag, full))
462 }
463}
464
465impl core::iter::FusedIterator for RegistryIter<'_, '_> {}
466
467#[derive(Debug)]
479#[cfg_attr(feature = "serde", derive(serde::Serialize))]
480#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
481#[non_exhaustive]
482pub enum ExtIterItem<'a> {
483 Descriptor(AnyDescriptor<'a>),
485 CustomExtension {
487 tag_extension: u8,
489 #[cfg_attr(
492 feature = "serde",
493 serde(serialize_with = "super::extension::registry::serialize_erased")
494 )]
495 value: Box<dyn super::extension::registry::ExtensionObject>,
496 },
497}
498
499pub struct ExtRegistryIter<'r, 'a> {
509 desc_reg: &'r DescriptorRegistry,
510 ext_reg: &'r super::extension::registry::ExtensionRegistry,
511 bytes: &'a [u8],
512 pos: usize,
513 fused: bool,
514 current_pds: Option<u32>,
515}
516
517impl<'r, 'a> ExtRegistryIter<'r, 'a> {
518 pub(crate) fn new(
519 desc_reg: &'r DescriptorRegistry,
520 ext_reg: &'r super::extension::registry::ExtensionRegistry,
521 bytes: &'a [u8],
522 inherited: Option<u32>,
523 ) -> Self {
524 Self {
525 desc_reg,
526 ext_reg,
527 bytes,
528 pos: 0,
529 fused: false,
530 current_pds: inherited,
531 }
532 }
533
534 #[must_use]
537 pub fn avs_scope(&self) -> Option<u32> {
538 self.current_pds
539 .filter(|p| *p == crate::descriptors::PDS_AVSA || *p == crate::descriptors::PDS_AVSV)
540 }
541}
542
543impl<'a> Iterator for ExtRegistryIter<'_, 'a> {
544 type Item = crate::Result<ExtIterItem<'a>>;
545
546 fn next(&mut self) -> Option<Self::Item> {
547 let (tag, full) = match crate::descriptors::any::next_loop_entry(
548 self.bytes,
549 &mut self.pos,
550 &mut self.fused,
551 )? {
552 Ok(v) => v,
553 Err(e) => return Some(Err(e)),
554 };
555
556 update_pds(&mut self.current_pds, tag, full);
557
558 let len = full.len() - 2;
559 if tag == crate::descriptors::extension::TAG && len >= 1 {
560 let tag_extension = full[2];
561 if self.ext_reg.has_custom(tag_extension) {
562 return Some(match self.ext_reg.parse_body(tag_extension, &full[3..]) {
563 Ok(super::extension::registry::RegisteredExtension::Custom {
564 tag_extension,
565 value,
566 }) => Ok(ExtIterItem::CustomExtension {
567 tag_extension,
568 value,
569 }),
570 Ok(super::extension::registry::RegisteredExtension::Builtin(d)) => {
571 Ok(ExtIterItem::Descriptor(AnyDescriptor::Extension(d)))
572 }
573 Err(e) => Err(e),
574 });
575 }
576 }
577
578 Some(
579 dispatch_entry(self.desc_reg, self.current_pds, tag, full).map(ExtIterItem::Descriptor),
580 )
581 }
582}
583
584impl core::iter::FusedIterator for ExtRegistryIter<'_, '_> {}
585
586#[cfg(test)]
587mod tests {
588 use super::*;
589 use crate::descriptors::private_data_specifier;
590 use crate::descriptors::private_data_specifier::{PDS_EACEM, PDS_NORDIG};
591 use crate::traits::DescriptorDef;
592 use alloc::{vec, vec::Vec};
593
594 #[test]
595 fn pds_constants_match_the_register() {
596 assert_eq!(
599 private_data_specifier::private_data_specifier_name(PDS_EACEM),
600 Some("EACEM/EICTA")
601 );
602 assert_eq!(
603 private_data_specifier::private_data_specifier_name(PDS_NORDIG),
604 Some("NorDig")
605 );
606 }
607
608 #[derive(Debug, PartialEq, Eq)]
609 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
610 struct PdsEacem {
611 v: u8,
612 }
613
614 impl<'a> broadcast_common::Parse<'a> for PdsEacem {
615 type Error = crate::error::Error;
616 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
617 if bytes.len() < 3 {
618 return Err(crate::error::Error::BufferTooShort(
619 broadcast_common::error::BufferTooShort {
620 need: 3,
621 have: bytes.len(),
622 what: "PdsEacem",
623 },
624 ));
625 }
626 Ok(Self { v: bytes[2] })
627 }
628 }
629
630 impl DescriptorDef<'_> for PdsEacem {
631 const TAG: u8 = 0x83;
632 const NAME: &'static str = "PDS_EACEM";
633 }
634
635 #[derive(Debug, PartialEq, Eq)]
636 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
637 struct PdsNordig {
638 w: u8,
639 }
640
641 impl<'a> broadcast_common::Parse<'a> for PdsNordig {
642 type Error = crate::error::Error;
643 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
644 if bytes.len() < 3 {
645 return Err(crate::error::Error::BufferTooShort(
646 broadcast_common::error::BufferTooShort {
647 need: 3,
648 have: bytes.len(),
649 what: "PdsNordig",
650 },
651 ));
652 }
653 Ok(Self { w: bytes[2] })
654 }
655 }
656
657 impl DescriptorDef<'_> for PdsNordig {
658 const TAG: u8 = 0x83;
659 const NAME: &'static str = "PDS_NORDIG";
660 }
661
662 #[derive(Debug, PartialEq, Eq)]
663 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
664 struct PdsAgnostic {
665 z: u8,
666 }
667
668 impl<'a> broadcast_common::Parse<'a> for PdsAgnostic {
669 type Error = crate::error::Error;
670 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
671 if bytes.len() < 3 {
672 return Err(crate::error::Error::BufferTooShort(
673 broadcast_common::error::BufferTooShort {
674 need: 3,
675 have: bytes.len(),
676 what: "PdsAgnostic",
677 },
678 ));
679 }
680 Ok(Self { z: bytes[2] })
681 }
682 }
683
684 impl DescriptorDef<'_> for PdsAgnostic {
685 const TAG: u8 = 0x84;
686 const NAME: &'static str = "PDS_AGNOSTIC";
687 }
688
689 fn pds_descriptor(pds: u32) -> Vec<u8> {
690 let mut v = vec![private_data_specifier::TAG, 4];
691 v.extend_from_slice(&pds.to_be_bytes());
692 v
693 }
694
695 #[test]
696 fn pds_scoped_same_tag_resolves_by_pds() {
697 let mut reg = DescriptorRegistry::new();
698 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
699 reg.register_for_pds::<PdsNordig>(PDS_NORDIG);
700
701 let mut bytes = Vec::new();
702 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
703 bytes.extend_from_slice(&[0x83, 0x01, 0xAA]);
704
705 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
706 assert_eq!(items.len(), 2);
707 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
708 match &items[1] {
709 AnyDescriptor::Other { tag, value } => {
710 assert_eq!(*tag, 0x83);
711 let c = value.downcast_ref::<PdsEacem>().unwrap();
712 assert_eq!(c.v, 0xAA);
713 }
714 other => panic!("expected Other (PdsEacem), got {other:?}"),
715 }
716
717 let mut bytes2 = Vec::new();
718 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
719 bytes2.extend_from_slice(&[0x83, 0x01, 0xBB]);
720
721 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
722 match &items2[1] {
723 AnyDescriptor::Other { tag, value } => {
724 assert_eq!(*tag, 0x83);
725 let c = value.downcast_ref::<PdsNordig>().unwrap();
726 assert_eq!(c.w, 0xBB);
727 }
728 other => panic!("expected Other (PdsNordig), got {other:?}"),
729 }
730 }
731
732 #[test]
733 fn pds_scoped_does_not_match_wrong_pds() {
734 let mut reg = DescriptorRegistry::new();
735 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
736
737 let mut bytes = Vec::new();
738 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
739 bytes.extend_from_slice(&[0x83, 0x01, 0xCC]);
740
741 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
742 assert_eq!(items.len(), 2);
743 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
744 match &items[1] {
745 AnyDescriptor::Unknown { tag, .. } => assert_eq!(*tag, 0x83),
746 other => panic!("expected Unknown (wrong PDS), got {other:?}"),
747 }
748 }
749
750 #[test]
753 fn avs2_and_tuwa_descriptors_are_scoped() {
754 use crate::descriptors::avs2_audio::Avs2AudioDescriptor;
755 use crate::descriptors::avs2_video::Avs2VideoDescriptor;
756 use crate::descriptors::private_data_specifier::{PDS_AVSA, PDS_AVSV};
757 use crate::descriptors::tuwa_avs3_video::TuwaAvs3VideoDescriptor;
758 let mut reg = DescriptorRegistry::new();
759 reg.with_avs2_video()
760 .with_avs2_audio()
761 .with_tuwa_avs3_video();
762
763 let v = [0x40, 5, 0x20, 0x42, 0x00, 0xA9, 0x5F];
764 let items: Vec<_> = reg.parse_loop(&v).collect::<Result<_, _>>().unwrap();
766 assert!(matches!(items[0], AnyDescriptor::NetworkName(_)));
767 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'V'];
769 b.extend_from_slice(&v);
770 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
771 match &items[1] {
772 AnyDescriptor::Other { tag: 0x40, value } => {
773 assert!(value.downcast_ref::<Avs2VideoDescriptor>().is_some());
774 }
775 other => panic!("expected Avs2Video, got {other:?}"),
776 }
777 let mut b = pds_descriptor(PDS_AVSV);
779 b.extend_from_slice(&v);
780 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
781 assert!(matches!(items[1], AnyDescriptor::Other { tag: 0x40, .. }));
782
783 let a = [0xD3, 2, 6, 0x20];
784 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'A'];
785 b.extend_from_slice(&a);
786 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
787 match &items[1] {
788 AnyDescriptor::Other { tag: 0xD3, value } => {
789 assert!(value.downcast_ref::<Avs2AudioDescriptor>().is_some());
790 }
791 other => panic!("expected Avs2Audio, got {other:?}"),
792 }
793 let mut b = pds_descriptor(PDS_AVSA);
794 b.extend_from_slice(&a);
795 assert!(matches!(
796 reg.parse_loop(&b).collect::<Result<Vec<_>, _>>().unwrap()[1],
797 AnyDescriptor::Other { tag: 0xD3, .. }
798 ));
799 let items: Vec<_> = reg.parse_loop(&a).collect::<Result<_, _>>().unwrap();
801 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD3, .. }));
802
803 let t = [62, 7, 0x22, 0x42, 0xAA, 0x4F, 9, 14, 9];
805 let items: Vec<_> = reg.parse_loop(&t).collect::<Result<_, _>>().unwrap();
806 match &items[0] {
807 AnyDescriptor::Other { tag: 62, value } => {
808 assert!(value.downcast_ref::<TuwaAvs3VideoDescriptor>().is_some());
809 }
810 other => panic!("expected TuwaAvs3Video, got {other:?}"),
811 }
812 let plain = DescriptorRegistry::new();
813 let items: Vec<_> = plain.parse_loop(&t).collect::<Result<_, _>>().unwrap();
814 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 62, .. }));
815 }
816
817 #[test]
822 fn program_info_registration_scopes_es_info_descriptors() {
823 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
824 use crate::descriptors::private_data_specifier::PDS_AVSV;
825 let program_info = [0x05, 4, b'A', b'V', b'S', b'V'];
826 let es_info = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
828 let mut reg = DescriptorRegistry::new();
829 reg.with_avs3_video();
830
831 let items: Vec<_> = reg.parse_loop(&es_info).collect::<Result<_, _>>().unwrap();
833 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD1, .. }));
834
835 let mut pi = reg.parse_loop(&program_info);
837 assert_eq!(pi.avs_scope(), None, "no entry consumed yet");
838 for item in pi.by_ref() {
839 item.unwrap();
840 }
841 let scope = pi.avs_scope();
842 assert_eq!(scope, Some(PDS_AVSV));
843 let items: Vec<_> = reg
844 .parse_loop_in_scope(&es_info, scope)
845 .collect::<Result<_, _>>()
846 .unwrap();
847 match &items[0] {
848 AnyDescriptor::Other { tag: 0xD1, value } => {
849 assert!(value.downcast_ref::<Avs3VideoDescriptor>().is_some());
850 }
851 other => panic!("expected Avs3Video via inherited scope, got {other:?}"),
852 }
853 let hevc = [0x05, 4, b'H', b'E', b'V', b'C'];
855 let mut pi = reg.parse_loop(&hevc);
856 for item in pi.by_ref() {
857 item.unwrap();
858 }
859 assert_eq!(pi.avs_scope(), None);
860 }
861
862 #[test]
865 fn avs3_video_descriptor_scopes() {
866 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
867 use crate::descriptors::private_data_specifier::PDS_AVSV;
868 let desc = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
869 let mut reg = DescriptorRegistry::new();
870 reg.with_avs3_video();
871 let check = |bytes: &[u8], idx: usize| {
872 let items: Vec<_> = reg.parse_loop(bytes).collect::<Result<_, _>>().unwrap();
873 match &items[idx] {
874 AnyDescriptor::Other { tag, value } => {
875 assert_eq!(*tag, 0xD1);
876 assert_eq!(
877 value
878 .downcast_ref::<Avs3VideoDescriptor>()
879 .unwrap()
880 .profile_id,
881 0x22
882 );
883 }
884 other => panic!("expected Other, got {other:?}"),
885 }
886 };
887 let mut pds = pds_descriptor(PDS_AVSV);
888 pds.extend_from_slice(&desc);
889 check(&pds, 1);
890 let mut registration = vec![0x05, 4, b'A', b'V', b'S', b'V'];
891 registration.extend_from_slice(&desc);
892 check(®istration, 1);
893 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
895 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD1, .. }));
896 let mut other = vec![0x05, 4, b'A', b'C', b'-', b'3'];
897 other.extend_from_slice(&desc);
898 let items: Vec<_> = reg.parse_loop(&other).collect::<Result<_, _>>().unwrap();
899 assert!(matches!(items[1], AnyDescriptor::Unknown { tag: 0xD1, .. }));
900 let adesc = [0xD2, 2, 0x72, 0x45];
902 let mut areg = DescriptorRegistry::new();
903 areg.with_avs3_audio();
904 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'A'];
905 b.extend_from_slice(&adesc);
906 let items: Vec<_> = areg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
907 assert!(matches!(items[1], AnyDescriptor::Other { tag: 0xD2, .. }));
908 }
909
910 #[test]
913 fn avs3_audio_descriptor_is_pds_scoped() {
914 use crate::descriptors::avs3_audio::Avs3AudioDescriptor;
915 use crate::descriptors::private_data_specifier::PDS_AVSA;
916 let desc = [0xD2, 6, 0x03, 0xAA, 0x95, 0x04, 0x00, 0x6A];
917 let mut reg = DescriptorRegistry::new();
918 reg.with_avs3_audio();
919
920 let mut bytes = Vec::new();
921 bytes.extend_from_slice(&pds_descriptor(PDS_AVSA));
922 bytes.extend_from_slice(&desc);
923 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
924 match &items[1] {
925 AnyDescriptor::Other { tag, value } => {
926 assert_eq!(*tag, 0xD2);
927 let d = value.downcast_ref::<Avs3AudioDescriptor>().unwrap();
928 assert_eq!(d.sampling_frequency_index, 3);
929 }
930 other => panic!("expected Other (Avs3AudioDescriptor), got {other:?}"),
931 }
932
933 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
935 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD2, .. }));
936 let mut other = Vec::new();
937 other.extend_from_slice(&pds_descriptor(PDS_NORDIG));
938 other.extend_from_slice(&desc);
939 let items: Vec<_> = reg.parse_loop(&other).collect::<Result<_, _>>().unwrap();
940 assert!(matches!(items[1], AnyDescriptor::Unknown { tag: 0xD2, .. }));
941 }
942
943 #[test]
946 fn china_caption_service_is_opt_in() {
947 use crate::descriptors::china_caption_service::ChinaCaptionServiceDescriptor;
948 let desc = [
949 0x86, 9, 0xE1, b'c', b'h', b'i', 0xC1, 0xC2, 0xFF, 0xE1, 0x00,
950 ];
951 let plain = DescriptorRegistry::new();
952 let items: Vec<_> = plain.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
953 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0x86, .. }));
954 let mut reg = DescriptorRegistry::new();
955 reg.with_china_caption_service();
956 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
957 match &items[0] {
958 AnyDescriptor::Other { tag, value } => {
959 assert_eq!(*tag, 0x86);
960 let d = value
961 .downcast_ref::<ChinaCaptionServiceDescriptor>()
962 .unwrap();
963 assert_eq!(d.services.len(), 1);
964 }
965 other => panic!("expected Other, got {other:?}"),
966 }
967 }
968
969 #[test]
970 fn atsc_caption_service_is_opt_in() {
971 use crate::descriptors::atsc_caption_service::AtscCaptionServiceDescriptor;
972 let desc = [0x86, 7, 0xE1, b'e', b'n', b'g', 0xC1, 0x7F, 0xFF];
973 let plain = DescriptorRegistry::new();
974 let items: Vec<_> = plain.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
975 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0x86, .. }));
976 let mut reg = DescriptorRegistry::new();
977 reg.with_atsc_caption_service();
978 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
979 match &items[0] {
980 AnyDescriptor::Other { value, .. } => {
981 let d = value
982 .downcast_ref::<AtscCaptionServiceDescriptor>()
983 .unwrap();
984 assert_eq!(d.services.len(), 1);
985 }
986 other => panic!("expected Other, got {other:?}"),
987 }
988 }
989
990 #[test]
991 fn pds_agnostic_matches_without_pds() {
992 let mut reg = DescriptorRegistry::new();
993 reg.register::<PdsAgnostic>();
994
995 let bytes = [0x84, 0x01, 0xDD];
996 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
997 assert_eq!(items.len(), 1);
998 match &items[0] {
999 AnyDescriptor::Other { tag, value } => {
1000 assert_eq!(*tag, 0x84);
1001 let c = value.downcast_ref::<PdsAgnostic>().unwrap();
1002 assert_eq!(c.z, 0xDD);
1003 }
1004 other => panic!("expected Other, got {other:?}"),
1005 }
1006 }
1007
1008 #[test]
1009 fn pds_scoped_takes_precedence_over_agnostic() {
1010 #[derive(Debug, PartialEq, Eq)]
1014 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
1015 struct Agnostic83 {
1016 a: u8,
1017 }
1018
1019 impl<'a> broadcast_common::Parse<'a> for Agnostic83 {
1020 type Error = crate::error::Error;
1021 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
1022 if bytes.len() < 3 {
1023 return Err(crate::error::Error::BufferTooShort(
1024 broadcast_common::error::BufferTooShort {
1025 need: 3,
1026 have: bytes.len(),
1027 what: "Agnostic83",
1028 },
1029 ));
1030 }
1031 Ok(Self { a: bytes[2] })
1032 }
1033 }
1034
1035 impl DescriptorDef<'_> for Agnostic83 {
1036 const TAG: u8 = 0x83;
1037 const NAME: &'static str = "AGNOSTIC_83";
1038 }
1039
1040 let mut reg = DescriptorRegistry::new();
1041 reg.register::<Agnostic83>();
1042 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
1043
1044 let items: Vec<_> = reg
1046 .parse_loop(&[0x83, 0x01, 0xEE])
1047 .collect::<Result<_, _>>()
1048 .unwrap();
1049 match &items[0] {
1050 AnyDescriptor::Other { value, .. } => {
1051 assert!(value.downcast_ref::<Agnostic83>().is_some());
1052 assert!(value.downcast_ref::<PdsEacem>().is_none());
1053 }
1054 other => panic!("expected Other, got {other:?}"),
1055 }
1056
1057 let mut bytes = Vec::new();
1059 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1060 bytes.extend_from_slice(&[0x83, 0x01, 0xFF]);
1061 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1062 match &items[1] {
1063 AnyDescriptor::Other { value, .. } => {
1064 assert!(value.downcast_ref::<PdsEacem>().is_some());
1065 assert!(value.downcast_ref::<Agnostic83>().is_none());
1066 }
1067 other => panic!("expected Other, got {other:?}"),
1068 }
1069 }
1070
1071 fn logical_channel_descriptor(service_id: u16, visible: bool, lcn: u16) -> Vec<u8> {
1072 let mut v = vec![crate::descriptors::logical_channel::TAG, 4];
1074 v.extend_from_slice(&service_id.to_be_bytes());
1075 let flags = (u8::from(visible) << 7) | ((lcn >> 8) as u8 & 0x03);
1076 v.push(flags);
1077 v.push((lcn & 0xFF) as u8);
1078 v
1079 }
1080
1081 #[test]
1082 fn logical_channel_pds_scoped_matches_correct_pds() {
1083 let mut reg = DescriptorRegistry::new();
1084 reg.with_logical_channel_for_pds(PDS_EACEM);
1085
1086 let mut bytes = Vec::new();
1087 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1088 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
1089
1090 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1091 assert_eq!(items.len(), 2);
1092 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
1093 match &items[1] {
1094 AnyDescriptor::LogicalChannel(lc) => {
1095 assert_eq!(lc.entries.len(), 1);
1096 assert_eq!(lc.entries[0].service_id, 0x1234);
1097 assert!(lc.entries[0].visible_service);
1098 assert_eq!(lc.entries[0].logical_channel_number, 101);
1099 }
1100 other => panic!("expected LogicalChannel, got {other:?}"),
1101 }
1102 }
1103
1104 #[test]
1105 fn logical_channel_pds_scoped_rejects_no_pds() {
1106 let mut reg = DescriptorRegistry::new();
1107 reg.with_logical_channel_for_pds(PDS_EACEM);
1108
1109 let bytes = logical_channel_descriptor(0x1234, true, 101);
1110 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1111 assert_eq!(items.len(), 1);
1112 assert!(matches!(
1113 &items[0],
1114 AnyDescriptor::Unknown { tag: 0x83, .. }
1115 ));
1116 }
1117
1118 #[test]
1119 fn logical_channel_pds_scoped_rejects_wrong_pds() {
1120 let mut reg = DescriptorRegistry::new();
1121 reg.with_logical_channel_for_pds(PDS_EACEM);
1122
1123 let mut bytes = Vec::new();
1124 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1125 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
1126
1127 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1128 assert_eq!(items.len(), 2);
1129 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
1130 assert!(matches!(
1131 &items[1],
1132 AnyDescriptor::Unknown { tag: 0x83, .. }
1133 ));
1134 }
1135
1136 #[test]
1137 fn logical_channel_pds_scoped_multiple_pds() {
1138 let mut reg = DescriptorRegistry::new();
1139 reg.with_logical_channel_for_pds(PDS_EACEM);
1140 reg.with_logical_channel_for_pds(PDS_NORDIG);
1141
1142 let mut bytes = Vec::new();
1144 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1145 bytes.extend_from_slice(&logical_channel_descriptor(0x0001, true, 1));
1146 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1147 assert!(matches!(&items[1], AnyDescriptor::LogicalChannel(_)));
1148
1149 let mut bytes2 = Vec::new();
1151 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1152 bytes2.extend_from_slice(&logical_channel_descriptor(0x0002, false, 2));
1153 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
1154 assert!(matches!(&items2[1], AnyDescriptor::LogicalChannel(_)));
1155 }
1156
1157 #[test]
1159 fn program_info_registration_scopes_es_info_with_extensions() {
1160 use crate::descriptors::any::DescriptorLoop;
1161 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
1162 use crate::descriptors::extension::registry::ExtensionRegistry;
1163 use crate::descriptors::private_data_specifier::PDS_AVSV;
1164 let program_info = [0x05, 4, b'A', b'V', b'S', b'V'];
1165 let es_info = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
1166 let mut reg = DescriptorRegistry::new();
1167 reg.with_avs3_video();
1168 let ext = ExtensionRegistry::new();
1169
1170 let items: Vec<_> = DescriptorLoop::new(&es_info)
1171 .iter_with_extensions(®, &ext)
1172 .collect::<Result<_, _>>()
1173 .unwrap();
1174 assert!(matches!(
1175 &items[0],
1176 ExtIterItem::Descriptor(AnyDescriptor::Unknown { tag: 0xD1, .. })
1177 ));
1178
1179 let mut pi = DescriptorLoop::new(&program_info).iter_with_extensions(®, &ext);
1180 for item in pi.by_ref() {
1181 item.unwrap();
1182 }
1183 let scope = pi.avs_scope();
1184 assert_eq!(scope, Some(PDS_AVSV));
1185 let items: Vec<_> = DescriptorLoop::new(&es_info)
1186 .iter_with_extensions_in_scope(®, &ext, scope)
1187 .collect::<Result<_, _>>()
1188 .unwrap();
1189 match &items[0] {
1190 ExtIterItem::Descriptor(AnyDescriptor::Other { tag: 0xD1, value }) => {
1191 assert!(value.downcast_ref::<Avs3VideoDescriptor>().is_some());
1192 }
1193 other => panic!("expected Avs3Video via inherited scope, got {other:?}"),
1194 }
1195 }
1196
1197 #[test]
1198 fn iter_with_extensions_surfaces_custom_extension() {
1199 use crate::descriptors::any::{AnyDescriptor, DescriptorLoop};
1200 use crate::descriptors::extension::registry::ExtensionRegistry;
1201
1202 #[derive(Debug, PartialEq, Eq)]
1203 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
1204 struct MyCustomExt {
1205 payload: Vec<u8>,
1206 }
1207
1208 impl<'a> broadcast_common::Parse<'a> for MyCustomExt {
1209 type Error = crate::error::Error;
1210 fn parse(sel: &'a [u8]) -> crate::Result<Self> {
1211 Ok(Self {
1212 payload: sel.to_vec(),
1213 })
1214 }
1215 }
1216
1217 impl crate::descriptors::extension::ExtensionBodyDef<'_> for MyCustomExt {
1218 const TAG_EXTENSION: u8 = 0x42;
1219 const NAME: &'static str = "MY_CUSTOM_EXT";
1220 }
1221
1222 let mut ext_reg = ExtensionRegistry::new();
1223 ext_reg.register::<MyCustomExt>();
1224
1225 let desc_reg = DescriptorRegistry::new();
1226
1227 let mut loop_bytes = vec![
1229 0x4D, 0x07, b'e', b'n', b'g', 0x02, b'H', b'i', 0x00, ];
1231 loop_bytes.extend_from_slice(&[0x7F, 0x03, 0x42, 0xAB, 0xCD]);
1233
1234 let dl = DescriptorLoop::new(&loop_bytes);
1235 let items: Vec<_> = dl
1236 .iter_with_extensions(&desc_reg, &ext_reg)
1237 .collect::<Result<_, _>>()
1238 .unwrap();
1239 assert_eq!(items.len(), 2);
1240 assert!(matches!(
1242 &items[0],
1243 ExtIterItem::Descriptor(AnyDescriptor::ShortEvent(_))
1244 ));
1245 match &items[1] {
1247 ExtIterItem::CustomExtension {
1248 tag_extension,
1249 value,
1250 } => {
1251 assert_eq!(*tag_extension, 0x42);
1252 let concrete = value.downcast_ref::<MyCustomExt>().unwrap();
1253 assert_eq!(concrete.payload, &[0xAB, 0xCD]);
1254 }
1255 other => panic!("expected CustomExtension, got {other:?}"),
1256 }
1257 }
1258}