1use alloc::boxed::Box;
69use alloc::collections::BTreeMap;
70use core::any::Any;
71
72use crate::descriptors::any::AnyDescriptor;
73use crate::descriptors::private_data_specifier::PDS_NORDIG;
74
75#[cfg(not(feature = "serde"))]
87pub trait DescriptorObject: core::fmt::Debug + Any + Send + Sync {
88 fn as_any(&self) -> &dyn Any;
90}
91
92#[cfg(feature = "serde")]
100pub trait DescriptorObject: core::fmt::Debug + Any + Send + Sync + erased_serde::Serialize {
101 fn as_any(&self) -> &dyn Any;
103}
104
105#[cfg(not(feature = "serde"))]
107impl<T> DescriptorObject for T
108where
109 T: core::fmt::Debug + Any + Send + Sync,
110{
111 fn as_any(&self) -> &dyn Any {
112 self
113 }
114}
115
116#[cfg(feature = "serde")]
118impl<T> DescriptorObject for T
119where
120 T: core::fmt::Debug + Any + Send + Sync + serde::Serialize,
121{
122 fn as_any(&self) -> &dyn Any {
123 self
124 }
125}
126
127impl dyn DescriptorObject {
139 #[must_use]
144 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
145 self.as_any().downcast_ref::<T>()
146 }
147
148 #[must_use]
150 pub fn is<T: Any>(&self) -> bool {
151 self.as_any().is::<T>()
152 }
153}
154
155#[cfg(feature = "serde")]
167#[allow(clippy::borrowed_box)]
168pub(crate) fn serialize_erased<S: serde::Serializer>(
169 v: &Box<dyn DescriptorObject>,
170 s: S,
171) -> Result<S::Ok, S::Error> {
172 erased_serde::serialize(&**v, s)
173}
174
175pub(crate) type CustomParse =
182 Box<dyn for<'a> Fn(&'a [u8]) -> crate::Result<Box<dyn DescriptorObject>> + Send + Sync>;
183
184#[derive(Default)]
214pub struct DescriptorRegistry {
215 custom: BTreeMap<(Option<u32>, u8), CustomParse>,
216 logical_channel: bool,
217 logical_channel_pds: alloc::collections::BTreeSet<u32>,
218}
219
220impl DescriptorRegistry {
221 #[must_use]
223 pub fn new() -> Self {
224 Self::default()
225 }
226
227 pub fn register<T>(&mut self) -> &mut Self
248 where
249 T: for<'a> crate::traits::DescriptorDef<'a> + DescriptorObject + 'static,
250 {
251 let tag = <T as crate::traits::DescriptorDef<'static>>::TAG;
252 self.custom.insert(
253 (None, tag),
254 Box::new(|b| {
255 Ok(Box::new(<T as broadcast_common::Parse>::parse(b)?)
256 as Box<dyn DescriptorObject>)
257 }),
258 );
259 self
260 }
261
262 pub fn register_for_pds<T>(&mut self, pds: u32) -> &mut Self
274 where
275 T: for<'a> crate::traits::DescriptorDef<'a> + DescriptorObject + 'static,
276 {
277 let tag = <T as crate::traits::DescriptorDef<'static>>::TAG;
278 self.custom.insert(
279 (Some(pds), tag),
280 Box::new(|b| {
281 Ok(Box::new(<T as broadcast_common::Parse>::parse(b)?)
282 as Box<dyn DescriptorObject>)
283 }),
284 );
285 self
286 }
287
288 pub fn with_logical_channel(&mut self) -> &mut Self {
294 self.logical_channel = true;
295 self
296 }
297
298 pub fn with_logical_channel_for_pds(&mut self, pds: u32) -> &mut Self {
310 self.logical_channel_pds.insert(pds);
311 self
312 }
313
314 pub fn with_nordig_lcn(&mut self) -> &mut Self {
318 self.register_for_pds::<crate::descriptors::nordig::NordigLogicalChannelV1>(PDS_NORDIG);
319 self.register_for_pds::<crate::descriptors::nordig::NordigLogicalChannelV2>(PDS_NORDIG);
320 self
321 }
322
323 pub fn with_avs3_audio(&mut self) -> &mut Self {
329 self.register_for_pds::<crate::descriptors::avs3_audio::Avs3AudioDescriptor>(
330 crate::descriptors::PDS_AVSA,
331 );
332 self
333 }
334
335 pub fn with_avs3_video(&mut self) -> &mut Self {
342 self.register_for_pds::<crate::descriptors::avs3_video::Avs3VideoDescriptor>(
343 crate::descriptors::PDS_AVSV,
344 );
345 self
346 }
347
348 pub fn with_avs2_video(&mut self) -> &mut Self {
353 self.register_for_pds::<crate::descriptors::avs2_video::Avs2VideoDescriptor>(
354 crate::descriptors::PDS_AVSV,
355 );
356 self
357 }
358
359 pub fn with_avs2_audio(&mut self) -> &mut Self {
363 self.register_for_pds::<crate::descriptors::avs2_audio::Avs2AudioDescriptor>(
364 crate::descriptors::PDS_AVSA,
365 );
366 self
367 }
368
369 pub fn with_tuwa_avs3_video(&mut self) -> &mut Self {
373 self.register::<crate::descriptors::tuwa_avs3_video::TuwaAvs3VideoDescriptor>()
374 }
375
376 pub fn with_china_caption_service(&mut self) -> &mut Self {
382 self.register::<crate::descriptors::china_caption_service::ChinaCaptionServiceDescriptor>()
383 }
384
385 pub fn with_atsc_caption_service(&mut self) -> &mut Self {
390 self.register::<crate::descriptors::atsc_caption_service::AtscCaptionServiceDescriptor>()
391 }
392
393 #[must_use]
403 pub fn parse_loop<'r, 'a>(&'r self, bytes: &'a [u8]) -> RegistryIter<'r, 'a> {
404 RegistryIter {
405 registry: self,
406 bytes,
407 pos: 0,
408 fused: false,
409 current_pds: None,
410 }
411 }
412
413 #[must_use]
427 pub fn parse_loop_in_scope<'r, 'a>(
428 &'r self,
429 bytes: &'a [u8],
430 inherited: Option<u32>,
431 ) -> RegistryIter<'r, 'a> {
432 RegistryIter {
433 registry: self,
434 bytes,
435 pos: 0,
436 fused: false,
437 current_pds: inherited,
438 }
439 }
440}
441
442pub struct RegistryIter<'r, 'a> {
450 registry: &'r DescriptorRegistry,
451 bytes: &'a [u8],
452 pos: usize,
453 fused: bool,
454 current_pds: Option<u32>,
455}
456
457pub(crate) fn dispatch_entry<'a>(
463 registry: &DescriptorRegistry,
464 current_pds: Option<u32>,
465 tag: u8,
466 full: &'a [u8],
467) -> crate::Result<AnyDescriptor<'a>> {
468 if let Some(pds) = current_pds
469 && let Some(parse_fn) = registry.custom.get(&(Some(pds), tag))
470 {
471 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
472 }
473 if let Some(parse_fn) = registry.custom.get(&(None, tag)) {
474 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
475 }
476 if let Some(pds) = current_pds
477 && tag == crate::descriptors::logical_channel::TAG
478 && registry.logical_channel_pds.contains(&pds)
479 {
480 use broadcast_common::Parse;
481 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
482 .map(AnyDescriptor::LogicalChannel);
483 }
484 if registry.logical_channel && tag == crate::descriptors::logical_channel::TAG {
485 use broadcast_common::Parse;
486 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
487 .map(AnyDescriptor::LogicalChannel);
488 }
489 if let Some(res) = AnyDescriptor::dispatch(tag, full) {
490 return res;
491 }
492 Ok(AnyDescriptor::Unknown {
493 tag,
494 body: &full[2..],
495 })
496}
497
498fn update_pds(current: &mut Option<u32>, tag: u8, full: &[u8]) {
499 if tag == crate::descriptors::registration::TAG {
505 use broadcast_common::Parse;
506 if let Ok(reg) = crate::descriptors::registration::RegistrationDescriptor::parse(full) {
507 let id = u32::from_be_bytes(reg.format_identifier);
508 if id == crate::descriptors::PDS_AVSA || id == crate::descriptors::PDS_AVSV {
509 *current = Some(id);
510 }
511 }
512 }
513 if tag == crate::descriptors::private_data_specifier::TAG {
514 use broadcast_common::Parse;
515 if let Ok(pds) =
516 crate::descriptors::private_data_specifier::PrivateDataSpecifierDescriptor::parse(full)
517 {
518 *current = Some(pds.private_data_specifier);
519 }
520 }
521}
522
523impl RegistryIter<'_, '_> {
524 #[must_use]
530 pub fn avs_scope(&self) -> Option<u32> {
531 self.current_pds
532 .filter(|p| *p == crate::descriptors::PDS_AVSA || *p == crate::descriptors::PDS_AVSV)
533 }
534}
535
536impl<'a> Iterator for RegistryIter<'_, 'a> {
537 type Item = crate::Result<AnyDescriptor<'a>>;
538
539 fn next(&mut self) -> Option<Self::Item> {
540 let (tag, full) = match crate::descriptors::any::next_loop_entry(
541 self.bytes,
542 &mut self.pos,
543 &mut self.fused,
544 )? {
545 Ok(v) => v,
546 Err(e) => return Some(Err(e)),
547 };
548
549 update_pds(&mut self.current_pds, tag, full);
550
551 Some(dispatch_entry(self.registry, self.current_pds, tag, full))
552 }
553}
554
555impl core::iter::FusedIterator for RegistryIter<'_, '_> {}
556
557#[derive(Debug)]
569#[cfg_attr(feature = "serde", derive(serde::Serialize))]
570#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
571#[non_exhaustive]
572pub enum ExtIterItem<'a> {
573 Descriptor(AnyDescriptor<'a>),
575 CustomExtension {
577 tag_extension: u8,
579 #[cfg_attr(
582 feature = "serde",
583 serde(serialize_with = "super::extension::registry::serialize_erased")
584 )]
585 value: Box<dyn super::extension::registry::ExtensionObject>,
586 },
587}
588
589pub struct ExtRegistryIter<'r, 'a> {
599 desc_reg: &'r DescriptorRegistry,
600 ext_reg: &'r super::extension::registry::ExtensionRegistry,
601 bytes: &'a [u8],
602 pos: usize,
603 fused: bool,
604 current_pds: Option<u32>,
605}
606
607impl<'r, 'a> ExtRegistryIter<'r, 'a> {
608 pub(crate) fn new(
609 desc_reg: &'r DescriptorRegistry,
610 ext_reg: &'r super::extension::registry::ExtensionRegistry,
611 bytes: &'a [u8],
612 inherited: Option<u32>,
613 ) -> Self {
614 Self {
615 desc_reg,
616 ext_reg,
617 bytes,
618 pos: 0,
619 fused: false,
620 current_pds: inherited,
621 }
622 }
623
624 #[must_use]
627 pub fn avs_scope(&self) -> Option<u32> {
628 self.current_pds
629 .filter(|p| *p == crate::descriptors::PDS_AVSA || *p == crate::descriptors::PDS_AVSV)
630 }
631}
632
633impl<'a> Iterator for ExtRegistryIter<'_, 'a> {
634 type Item = crate::Result<ExtIterItem<'a>>;
635
636 fn next(&mut self) -> Option<Self::Item> {
637 let (tag, full) = match crate::descriptors::any::next_loop_entry(
638 self.bytes,
639 &mut self.pos,
640 &mut self.fused,
641 )? {
642 Ok(v) => v,
643 Err(e) => return Some(Err(e)),
644 };
645
646 update_pds(&mut self.current_pds, tag, full);
647
648 let len = full.len() - 2;
649 if tag == crate::descriptors::extension::TAG && len >= 1 {
650 let tag_extension = full[2];
651 if self.ext_reg.has_custom(tag_extension) {
652 return Some(match self.ext_reg.parse_body(tag_extension, &full[3..]) {
653 Ok(super::extension::registry::RegisteredExtension::Custom {
654 tag_extension,
655 value,
656 }) => Ok(ExtIterItem::CustomExtension {
657 tag_extension,
658 value,
659 }),
660 Ok(super::extension::registry::RegisteredExtension::Builtin(d)) => {
661 Ok(ExtIterItem::Descriptor(AnyDescriptor::Extension(d)))
662 }
663 Err(e) => Err(e),
664 });
665 }
666 }
667
668 Some(
669 dispatch_entry(self.desc_reg, self.current_pds, tag, full).map(ExtIterItem::Descriptor),
670 )
671 }
672}
673
674impl core::iter::FusedIterator for ExtRegistryIter<'_, '_> {}
675
676#[cfg(test)]
677mod tests {
678 use super::*;
679 use crate::descriptors::private_data_specifier;
680 use crate::descriptors::private_data_specifier::{PDS_EACEM, PDS_NORDIG};
681 use crate::traits::DescriptorDef;
682
683 #[test]
684 fn pds_constants_match_the_register() {
685 assert_eq!(
688 private_data_specifier::private_data_specifier_name(PDS_EACEM),
689 Some("EACEM/EICTA")
690 );
691 assert_eq!(
692 private_data_specifier::private_data_specifier_name(PDS_NORDIG),
693 Some("NorDig")
694 );
695 }
696
697 #[derive(Debug, PartialEq, Eq)]
698 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
699 struct PdsEacem {
700 v: u8,
701 }
702
703 impl<'a> broadcast_common::Parse<'a> for PdsEacem {
704 type Error = crate::error::Error;
705 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
706 if bytes.len() < 3 {
707 return Err(crate::error::Error::BufferTooShort {
708 need: 3,
709 have: bytes.len(),
710 what: "PdsEacem",
711 });
712 }
713 Ok(Self { v: bytes[2] })
714 }
715 }
716
717 impl DescriptorDef<'_> for PdsEacem {
718 const TAG: u8 = 0x83;
719 const NAME: &'static str = "PDS_EACEM";
720 }
721
722 #[derive(Debug, PartialEq, Eq)]
723 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
724 struct PdsNordig {
725 w: u8,
726 }
727
728 impl<'a> broadcast_common::Parse<'a> for PdsNordig {
729 type Error = crate::error::Error;
730 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
731 if bytes.len() < 3 {
732 return Err(crate::error::Error::BufferTooShort {
733 need: 3,
734 have: bytes.len(),
735 what: "PdsNordig",
736 });
737 }
738 Ok(Self { w: bytes[2] })
739 }
740 }
741
742 impl DescriptorDef<'_> for PdsNordig {
743 const TAG: u8 = 0x83;
744 const NAME: &'static str = "PDS_NORDIG";
745 }
746
747 #[derive(Debug, PartialEq, Eq)]
748 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
749 struct PdsAgnostic {
750 z: u8,
751 }
752
753 impl<'a> broadcast_common::Parse<'a> for PdsAgnostic {
754 type Error = crate::error::Error;
755 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
756 if bytes.len() < 3 {
757 return Err(crate::error::Error::BufferTooShort {
758 need: 3,
759 have: bytes.len(),
760 what: "PdsAgnostic",
761 });
762 }
763 Ok(Self { z: bytes[2] })
764 }
765 }
766
767 impl DescriptorDef<'_> for PdsAgnostic {
768 const TAG: u8 = 0x84;
769 const NAME: &'static str = "PDS_AGNOSTIC";
770 }
771
772 fn pds_descriptor(pds: u32) -> Vec<u8> {
773 let mut v = vec![private_data_specifier::TAG, 4];
774 v.extend_from_slice(&pds.to_be_bytes());
775 v
776 }
777
778 #[test]
779 fn pds_scoped_same_tag_resolves_by_pds() {
780 let mut reg = DescriptorRegistry::new();
781 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
782 reg.register_for_pds::<PdsNordig>(PDS_NORDIG);
783
784 let mut bytes = Vec::new();
785 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
786 bytes.extend_from_slice(&[0x83, 0x01, 0xAA]);
787
788 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
789 assert_eq!(items.len(), 2);
790 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
791 match &items[1] {
792 AnyDescriptor::Other { tag, value } => {
793 assert_eq!(*tag, 0x83);
794 let c = value.downcast_ref::<PdsEacem>().unwrap();
795 assert_eq!(c.v, 0xAA);
796 }
797 other => panic!("expected Other (PdsEacem), got {other:?}"),
798 }
799
800 let mut bytes2 = Vec::new();
801 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
802 bytes2.extend_from_slice(&[0x83, 0x01, 0xBB]);
803
804 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
805 match &items2[1] {
806 AnyDescriptor::Other { tag, value } => {
807 assert_eq!(*tag, 0x83);
808 let c = value.downcast_ref::<PdsNordig>().unwrap();
809 assert_eq!(c.w, 0xBB);
810 }
811 other => panic!("expected Other (PdsNordig), got {other:?}"),
812 }
813 }
814
815 #[test]
816 fn pds_scoped_does_not_match_wrong_pds() {
817 let mut reg = DescriptorRegistry::new();
818 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
819
820 let mut bytes = Vec::new();
821 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
822 bytes.extend_from_slice(&[0x83, 0x01, 0xCC]);
823
824 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
825 assert_eq!(items.len(), 2);
826 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
827 match &items[1] {
828 AnyDescriptor::Unknown { tag, .. } => assert_eq!(*tag, 0x83),
829 other => panic!("expected Unknown (wrong PDS), got {other:?}"),
830 }
831 }
832
833 #[test]
836 fn avs2_and_tuwa_descriptors_are_scoped() {
837 use crate::descriptors::avs2_audio::Avs2AudioDescriptor;
838 use crate::descriptors::avs2_video::Avs2VideoDescriptor;
839 use crate::descriptors::private_data_specifier::{PDS_AVSA, PDS_AVSV};
840 use crate::descriptors::tuwa_avs3_video::TuwaAvs3VideoDescriptor;
841 let mut reg = DescriptorRegistry::new();
842 reg.with_avs2_video()
843 .with_avs2_audio()
844 .with_tuwa_avs3_video();
845
846 let v = [0x40, 5, 0x20, 0x42, 0x00, 0xA9, 0x5F];
847 let items: Vec<_> = reg.parse_loop(&v).collect::<Result<_, _>>().unwrap();
849 assert!(matches!(items[0], AnyDescriptor::NetworkName(_)));
850 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'V'];
852 b.extend_from_slice(&v);
853 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
854 match &items[1] {
855 AnyDescriptor::Other { tag: 0x40, value } => {
856 assert!(value.downcast_ref::<Avs2VideoDescriptor>().is_some());
857 }
858 other => panic!("expected Avs2Video, got {other:?}"),
859 }
860 let mut b = pds_descriptor(PDS_AVSV);
862 b.extend_from_slice(&v);
863 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
864 assert!(matches!(items[1], AnyDescriptor::Other { tag: 0x40, .. }));
865
866 let a = [0xD3, 2, 6, 0x20];
867 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'A'];
868 b.extend_from_slice(&a);
869 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
870 match &items[1] {
871 AnyDescriptor::Other { tag: 0xD3, value } => {
872 assert!(value.downcast_ref::<Avs2AudioDescriptor>().is_some());
873 }
874 other => panic!("expected Avs2Audio, got {other:?}"),
875 }
876 let mut b = pds_descriptor(PDS_AVSA);
877 b.extend_from_slice(&a);
878 assert!(matches!(
879 reg.parse_loop(&b).collect::<Result<Vec<_>, _>>().unwrap()[1],
880 AnyDescriptor::Other { tag: 0xD3, .. }
881 ));
882 let items: Vec<_> = reg.parse_loop(&a).collect::<Result<_, _>>().unwrap();
884 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD3, .. }));
885
886 let t = [62, 7, 0x22, 0x42, 0xAA, 0x4F, 9, 14, 9];
888 let items: Vec<_> = reg.parse_loop(&t).collect::<Result<_, _>>().unwrap();
889 match &items[0] {
890 AnyDescriptor::Other { tag: 62, value } => {
891 assert!(value.downcast_ref::<TuwaAvs3VideoDescriptor>().is_some());
892 }
893 other => panic!("expected TuwaAvs3Video, got {other:?}"),
894 }
895 let plain = DescriptorRegistry::new();
896 let items: Vec<_> = plain.parse_loop(&t).collect::<Result<_, _>>().unwrap();
897 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 62, .. }));
898 }
899
900 #[test]
905 fn program_info_registration_scopes_es_info_descriptors() {
906 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
907 use crate::descriptors::private_data_specifier::PDS_AVSV;
908 let program_info = [0x05, 4, b'A', b'V', b'S', b'V'];
909 let es_info = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
911 let mut reg = DescriptorRegistry::new();
912 reg.with_avs3_video();
913
914 let items: Vec<_> = reg.parse_loop(&es_info).collect::<Result<_, _>>().unwrap();
916 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD1, .. }));
917
918 let mut pi = reg.parse_loop(&program_info);
920 assert_eq!(pi.avs_scope(), None, "no entry consumed yet");
921 for item in pi.by_ref() {
922 item.unwrap();
923 }
924 let scope = pi.avs_scope();
925 assert_eq!(scope, Some(PDS_AVSV));
926 let items: Vec<_> = reg
927 .parse_loop_in_scope(&es_info, scope)
928 .collect::<Result<_, _>>()
929 .unwrap();
930 match &items[0] {
931 AnyDescriptor::Other { tag: 0xD1, value } => {
932 assert!(value.downcast_ref::<Avs3VideoDescriptor>().is_some());
933 }
934 other => panic!("expected Avs3Video via inherited scope, got {other:?}"),
935 }
936 let hevc = [0x05, 4, b'H', b'E', b'V', b'C'];
938 let mut pi = reg.parse_loop(&hevc);
939 for item in pi.by_ref() {
940 item.unwrap();
941 }
942 assert_eq!(pi.avs_scope(), None);
943 }
944
945 #[test]
948 fn avs3_video_descriptor_scopes() {
949 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
950 use crate::descriptors::private_data_specifier::PDS_AVSV;
951 let desc = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
952 let mut reg = DescriptorRegistry::new();
953 reg.with_avs3_video();
954 let check = |bytes: &[u8], idx: usize| {
955 let items: Vec<_> = reg.parse_loop(bytes).collect::<Result<_, _>>().unwrap();
956 match &items[idx] {
957 AnyDescriptor::Other { tag, value } => {
958 assert_eq!(*tag, 0xD1);
959 assert_eq!(
960 value
961 .downcast_ref::<Avs3VideoDescriptor>()
962 .unwrap()
963 .profile_id,
964 0x22
965 );
966 }
967 other => panic!("expected Other, got {other:?}"),
968 }
969 };
970 let mut pds = pds_descriptor(PDS_AVSV);
971 pds.extend_from_slice(&desc);
972 check(&pds, 1);
973 let mut registration = vec![0x05, 4, b'A', b'V', b'S', b'V'];
974 registration.extend_from_slice(&desc);
975 check(®istration, 1);
976 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
978 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD1, .. }));
979 let mut other = vec![0x05, 4, b'A', b'C', b'-', b'3'];
980 other.extend_from_slice(&desc);
981 let items: Vec<_> = reg.parse_loop(&other).collect::<Result<_, _>>().unwrap();
982 assert!(matches!(items[1], AnyDescriptor::Unknown { tag: 0xD1, .. }));
983 let adesc = [0xD2, 2, 0x72, 0x45];
985 let mut areg = DescriptorRegistry::new();
986 areg.with_avs3_audio();
987 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'A'];
988 b.extend_from_slice(&adesc);
989 let items: Vec<_> = areg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
990 assert!(matches!(items[1], AnyDescriptor::Other { tag: 0xD2, .. }));
991 }
992
993 #[test]
996 fn avs3_audio_descriptor_is_pds_scoped() {
997 use crate::descriptors::avs3_audio::Avs3AudioDescriptor;
998 use crate::descriptors::private_data_specifier::PDS_AVSA;
999 let desc = [0xD2, 6, 0x03, 0xAA, 0x95, 0x04, 0x00, 0x6A];
1000 let mut reg = DescriptorRegistry::new();
1001 reg.with_avs3_audio();
1002
1003 let mut bytes = Vec::new();
1004 bytes.extend_from_slice(&pds_descriptor(PDS_AVSA));
1005 bytes.extend_from_slice(&desc);
1006 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1007 match &items[1] {
1008 AnyDescriptor::Other { tag, value } => {
1009 assert_eq!(*tag, 0xD2);
1010 let d = value.downcast_ref::<Avs3AudioDescriptor>().unwrap();
1011 assert_eq!(d.sampling_frequency_index, 3);
1012 }
1013 other => panic!("expected Other (Avs3AudioDescriptor), got {other:?}"),
1014 }
1015
1016 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1018 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD2, .. }));
1019 let mut other = Vec::new();
1020 other.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1021 other.extend_from_slice(&desc);
1022 let items: Vec<_> = reg.parse_loop(&other).collect::<Result<_, _>>().unwrap();
1023 assert!(matches!(items[1], AnyDescriptor::Unknown { tag: 0xD2, .. }));
1024 }
1025
1026 #[test]
1029 fn china_caption_service_is_opt_in() {
1030 use crate::descriptors::china_caption_service::ChinaCaptionServiceDescriptor;
1031 let desc = [
1032 0x86, 9, 0xE1, b'c', b'h', b'i', 0xC1, 0xC2, 0xFF, 0xE1, 0x00,
1033 ];
1034 let plain = DescriptorRegistry::new();
1035 let items: Vec<_> = plain.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1036 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0x86, .. }));
1037 let mut reg = DescriptorRegistry::new();
1038 reg.with_china_caption_service();
1039 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1040 match &items[0] {
1041 AnyDescriptor::Other { tag, value } => {
1042 assert_eq!(*tag, 0x86);
1043 let d = value
1044 .downcast_ref::<ChinaCaptionServiceDescriptor>()
1045 .unwrap();
1046 assert_eq!(d.services.len(), 1);
1047 }
1048 other => panic!("expected Other, got {other:?}"),
1049 }
1050 }
1051
1052 #[test]
1053 fn atsc_caption_service_is_opt_in() {
1054 use crate::descriptors::atsc_caption_service::AtscCaptionServiceDescriptor;
1055 let desc = [0x86, 7, 0xE1, b'e', b'n', b'g', 0xC1, 0x7F, 0xFF];
1056 let plain = DescriptorRegistry::new();
1057 let items: Vec<_> = plain.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1058 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0x86, .. }));
1059 let mut reg = DescriptorRegistry::new();
1060 reg.with_atsc_caption_service();
1061 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1062 match &items[0] {
1063 AnyDescriptor::Other { value, .. } => {
1064 let d = value
1065 .downcast_ref::<AtscCaptionServiceDescriptor>()
1066 .unwrap();
1067 assert_eq!(d.services.len(), 1);
1068 }
1069 other => panic!("expected Other, got {other:?}"),
1070 }
1071 }
1072
1073 #[test]
1074 fn pds_agnostic_matches_without_pds() {
1075 let mut reg = DescriptorRegistry::new();
1076 reg.register::<PdsAgnostic>();
1077
1078 let bytes = [0x84, 0x01, 0xDD];
1079 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1080 assert_eq!(items.len(), 1);
1081 match &items[0] {
1082 AnyDescriptor::Other { tag, value } => {
1083 assert_eq!(*tag, 0x84);
1084 let c = value.downcast_ref::<PdsAgnostic>().unwrap();
1085 assert_eq!(c.z, 0xDD);
1086 }
1087 other => panic!("expected Other, got {other:?}"),
1088 }
1089 }
1090
1091 #[test]
1092 fn pds_scoped_takes_precedence_over_agnostic() {
1093 #[derive(Debug, PartialEq, Eq)]
1097 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
1098 struct Agnostic83 {
1099 a: u8,
1100 }
1101
1102 impl<'a> broadcast_common::Parse<'a> for Agnostic83 {
1103 type Error = crate::error::Error;
1104 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
1105 if bytes.len() < 3 {
1106 return Err(crate::error::Error::BufferTooShort {
1107 need: 3,
1108 have: bytes.len(),
1109 what: "Agnostic83",
1110 });
1111 }
1112 Ok(Self { a: bytes[2] })
1113 }
1114 }
1115
1116 impl DescriptorDef<'_> for Agnostic83 {
1117 const TAG: u8 = 0x83;
1118 const NAME: &'static str = "AGNOSTIC_83";
1119 }
1120
1121 let mut reg = DescriptorRegistry::new();
1122 reg.register::<Agnostic83>();
1123 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
1124
1125 let items: Vec<_> = reg
1127 .parse_loop(&[0x83, 0x01, 0xEE])
1128 .collect::<Result<_, _>>()
1129 .unwrap();
1130 match &items[0] {
1131 AnyDescriptor::Other { value, .. } => {
1132 assert!(value.downcast_ref::<Agnostic83>().is_some());
1133 assert!(value.downcast_ref::<PdsEacem>().is_none());
1134 }
1135 other => panic!("expected Other, got {other:?}"),
1136 }
1137
1138 let mut bytes = Vec::new();
1140 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1141 bytes.extend_from_slice(&[0x83, 0x01, 0xFF]);
1142 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1143 match &items[1] {
1144 AnyDescriptor::Other { value, .. } => {
1145 assert!(value.downcast_ref::<PdsEacem>().is_some());
1146 assert!(value.downcast_ref::<Agnostic83>().is_none());
1147 }
1148 other => panic!("expected Other, got {other:?}"),
1149 }
1150 }
1151
1152 fn logical_channel_descriptor(service_id: u16, visible: bool, lcn: u16) -> Vec<u8> {
1153 let mut v = vec![crate::descriptors::logical_channel::TAG, 4];
1155 v.extend_from_slice(&service_id.to_be_bytes());
1156 let flags = (u8::from(visible) << 7) | ((lcn >> 8) as u8 & 0x03);
1157 v.push(flags);
1158 v.push((lcn & 0xFF) as u8);
1159 v
1160 }
1161
1162 #[test]
1163 fn logical_channel_pds_scoped_matches_correct_pds() {
1164 let mut reg = DescriptorRegistry::new();
1165 reg.with_logical_channel_for_pds(PDS_EACEM);
1166
1167 let mut bytes = Vec::new();
1168 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1169 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
1170
1171 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1172 assert_eq!(items.len(), 2);
1173 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
1174 match &items[1] {
1175 AnyDescriptor::LogicalChannel(lc) => {
1176 assert_eq!(lc.entries.len(), 1);
1177 assert_eq!(lc.entries[0].service_id, 0x1234);
1178 assert!(lc.entries[0].visible_service);
1179 assert_eq!(lc.entries[0].logical_channel_number, 101);
1180 }
1181 other => panic!("expected LogicalChannel, got {other:?}"),
1182 }
1183 }
1184
1185 #[test]
1186 fn logical_channel_pds_scoped_rejects_no_pds() {
1187 let mut reg = DescriptorRegistry::new();
1188 reg.with_logical_channel_for_pds(PDS_EACEM);
1189
1190 let bytes = logical_channel_descriptor(0x1234, true, 101);
1191 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1192 assert_eq!(items.len(), 1);
1193 assert!(matches!(
1194 &items[0],
1195 AnyDescriptor::Unknown { tag: 0x83, .. }
1196 ));
1197 }
1198
1199 #[test]
1200 fn logical_channel_pds_scoped_rejects_wrong_pds() {
1201 let mut reg = DescriptorRegistry::new();
1202 reg.with_logical_channel_for_pds(PDS_EACEM);
1203
1204 let mut bytes = Vec::new();
1205 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1206 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
1207
1208 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1209 assert_eq!(items.len(), 2);
1210 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
1211 assert!(matches!(
1212 &items[1],
1213 AnyDescriptor::Unknown { tag: 0x83, .. }
1214 ));
1215 }
1216
1217 #[test]
1218 fn logical_channel_pds_scoped_multiple_pds() {
1219 let mut reg = DescriptorRegistry::new();
1220 reg.with_logical_channel_for_pds(PDS_EACEM);
1221 reg.with_logical_channel_for_pds(PDS_NORDIG);
1222
1223 let mut bytes = Vec::new();
1225 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1226 bytes.extend_from_slice(&logical_channel_descriptor(0x0001, true, 1));
1227 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1228 assert!(matches!(&items[1], AnyDescriptor::LogicalChannel(_)));
1229
1230 let mut bytes2 = Vec::new();
1232 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1233 bytes2.extend_from_slice(&logical_channel_descriptor(0x0002, false, 2));
1234 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
1235 assert!(matches!(&items2[1], AnyDescriptor::LogicalChannel(_)));
1236 }
1237
1238 #[test]
1240 fn program_info_registration_scopes_es_info_with_extensions() {
1241 use crate::descriptors::any::DescriptorLoop;
1242 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
1243 use crate::descriptors::extension::registry::ExtensionRegistry;
1244 use crate::descriptors::private_data_specifier::PDS_AVSV;
1245 let program_info = [0x05, 4, b'A', b'V', b'S', b'V'];
1246 let es_info = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
1247 let mut reg = DescriptorRegistry::new();
1248 reg.with_avs3_video();
1249 let ext = ExtensionRegistry::new();
1250
1251 let items: Vec<_> = DescriptorLoop::new(&es_info)
1252 .iter_with_extensions(®, &ext)
1253 .collect::<Result<_, _>>()
1254 .unwrap();
1255 assert!(matches!(
1256 &items[0],
1257 ExtIterItem::Descriptor(AnyDescriptor::Unknown { tag: 0xD1, .. })
1258 ));
1259
1260 let mut pi = DescriptorLoop::new(&program_info).iter_with_extensions(®, &ext);
1261 for item in pi.by_ref() {
1262 item.unwrap();
1263 }
1264 let scope = pi.avs_scope();
1265 assert_eq!(scope, Some(PDS_AVSV));
1266 let items: Vec<_> = DescriptorLoop::new(&es_info)
1267 .iter_with_extensions_in_scope(®, &ext, scope)
1268 .collect::<Result<_, _>>()
1269 .unwrap();
1270 match &items[0] {
1271 ExtIterItem::Descriptor(AnyDescriptor::Other { tag: 0xD1, value }) => {
1272 assert!(value.downcast_ref::<Avs3VideoDescriptor>().is_some());
1273 }
1274 other => panic!("expected Avs3Video via inherited scope, got {other:?}"),
1275 }
1276 }
1277
1278 #[test]
1279 fn iter_with_extensions_surfaces_custom_extension() {
1280 use crate::descriptors::any::{AnyDescriptor, DescriptorLoop};
1281 use crate::descriptors::extension::registry::ExtensionRegistry;
1282
1283 #[derive(Debug, PartialEq, Eq)]
1284 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
1285 struct MyCustomExt {
1286 payload: Vec<u8>,
1287 }
1288
1289 impl<'a> broadcast_common::Parse<'a> for MyCustomExt {
1290 type Error = crate::error::Error;
1291 fn parse(sel: &'a [u8]) -> crate::Result<Self> {
1292 Ok(Self {
1293 payload: sel.to_vec(),
1294 })
1295 }
1296 }
1297
1298 impl crate::descriptors::extension::ExtensionBodyDef<'_> for MyCustomExt {
1299 const TAG_EXTENSION: u8 = 0x42;
1300 const NAME: &'static str = "MY_CUSTOM_EXT";
1301 }
1302
1303 let mut ext_reg = ExtensionRegistry::new();
1304 ext_reg.register::<MyCustomExt>();
1305
1306 let desc_reg = DescriptorRegistry::new();
1307
1308 let mut loop_bytes = vec![
1310 0x4D, 0x07, b'e', b'n', b'g', 0x02, b'H', b'i', 0x00, ];
1312 loop_bytes.extend_from_slice(&[0x7F, 0x03, 0x42, 0xAB, 0xCD]);
1314
1315 let dl = DescriptorLoop::new(&loop_bytes);
1316 let items: Vec<_> = dl
1317 .iter_with_extensions(&desc_reg, &ext_reg)
1318 .collect::<Result<_, _>>()
1319 .unwrap();
1320 assert_eq!(items.len(), 2);
1321 assert!(matches!(
1323 &items[0],
1324 ExtIterItem::Descriptor(AnyDescriptor::ShortEvent(_))
1325 ));
1326 match &items[1] {
1328 ExtIterItem::CustomExtension {
1329 tag_extension,
1330 value,
1331 } => {
1332 assert_eq!(*tag_extension, 0x42);
1333 let concrete = value.downcast_ref::<MyCustomExt>().unwrap();
1334 assert_eq!(concrete.payload, &[0xAB, 0xCD]);
1335 }
1336 other => panic!("expected CustomExtension, got {other:?}"),
1337 }
1338 }
1339}