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 #[must_use]
395 pub fn parse_loop<'r, 'a>(&'r self, bytes: &'a [u8]) -> RegistryIter<'r, 'a> {
396 RegistryIter {
397 registry: self,
398 bytes,
399 pos: 0,
400 fused: false,
401 current_pds: None,
402 }
403 }
404
405 #[must_use]
419 pub fn parse_loop_in_scope<'r, 'a>(
420 &'r self,
421 bytes: &'a [u8],
422 inherited: Option<u32>,
423 ) -> RegistryIter<'r, 'a> {
424 RegistryIter {
425 registry: self,
426 bytes,
427 pos: 0,
428 fused: false,
429 current_pds: inherited,
430 }
431 }
432}
433
434pub struct RegistryIter<'r, 'a> {
442 registry: &'r DescriptorRegistry,
443 bytes: &'a [u8],
444 pos: usize,
445 fused: bool,
446 current_pds: Option<u32>,
447}
448
449pub(crate) fn dispatch_entry<'a>(
455 registry: &DescriptorRegistry,
456 current_pds: Option<u32>,
457 tag: u8,
458 full: &'a [u8],
459) -> crate::Result<AnyDescriptor<'a>> {
460 if let Some(pds) = current_pds
461 && let Some(parse_fn) = registry.custom.get(&(Some(pds), tag))
462 {
463 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
464 }
465 if let Some(parse_fn) = registry.custom.get(&(None, tag)) {
466 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
467 }
468 if let Some(pds) = current_pds
469 && tag == crate::descriptors::logical_channel::TAG
470 && registry.logical_channel_pds.contains(&pds)
471 {
472 use broadcast_common::Parse;
473 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
474 .map(AnyDescriptor::LogicalChannel);
475 }
476 if registry.logical_channel && tag == crate::descriptors::logical_channel::TAG {
477 use broadcast_common::Parse;
478 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
479 .map(AnyDescriptor::LogicalChannel);
480 }
481 if let Some(res) = AnyDescriptor::dispatch(tag, full) {
482 return res;
483 }
484 Ok(AnyDescriptor::Unknown {
485 tag,
486 body: &full[2..],
487 })
488}
489
490fn update_pds(current: &mut Option<u32>, tag: u8, full: &[u8]) {
491 if tag == crate::descriptors::registration::TAG {
497 use broadcast_common::Parse;
498 if let Ok(reg) = crate::descriptors::registration::RegistrationDescriptor::parse(full) {
499 let id = u32::from_be_bytes(reg.format_identifier);
500 if id == crate::descriptors::PDS_AVSA || id == crate::descriptors::PDS_AVSV {
501 *current = Some(id);
502 }
503 }
504 }
505 if tag == crate::descriptors::private_data_specifier::TAG {
506 use broadcast_common::Parse;
507 if let Ok(pds) =
508 crate::descriptors::private_data_specifier::PrivateDataSpecifierDescriptor::parse(full)
509 {
510 *current = Some(pds.private_data_specifier);
511 }
512 }
513}
514
515impl RegistryIter<'_, '_> {
516 #[must_use]
522 pub fn avs_scope(&self) -> Option<u32> {
523 self.current_pds
524 .filter(|p| *p == crate::descriptors::PDS_AVSA || *p == crate::descriptors::PDS_AVSV)
525 }
526}
527
528impl<'a> Iterator for RegistryIter<'_, 'a> {
529 type Item = crate::Result<AnyDescriptor<'a>>;
530
531 fn next(&mut self) -> Option<Self::Item> {
532 let (tag, full) = match crate::descriptors::any::next_loop_entry(
533 self.bytes,
534 &mut self.pos,
535 &mut self.fused,
536 )? {
537 Ok(v) => v,
538 Err(e) => return Some(Err(e)),
539 };
540
541 update_pds(&mut self.current_pds, tag, full);
542
543 Some(dispatch_entry(self.registry, self.current_pds, tag, full))
544 }
545}
546
547impl core::iter::FusedIterator for RegistryIter<'_, '_> {}
548
549#[derive(Debug)]
561#[cfg_attr(feature = "serde", derive(serde::Serialize))]
562#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
563#[non_exhaustive]
564pub enum ExtIterItem<'a> {
565 Descriptor(AnyDescriptor<'a>),
567 CustomExtension {
569 tag_extension: u8,
571 #[cfg_attr(
574 feature = "serde",
575 serde(serialize_with = "super::extension::registry::serialize_erased")
576 )]
577 value: Box<dyn super::extension::registry::ExtensionObject>,
578 },
579}
580
581pub struct ExtRegistryIter<'r, 'a> {
591 desc_reg: &'r DescriptorRegistry,
592 ext_reg: &'r super::extension::registry::ExtensionRegistry,
593 bytes: &'a [u8],
594 pos: usize,
595 fused: bool,
596 current_pds: Option<u32>,
597}
598
599impl<'r, 'a> ExtRegistryIter<'r, 'a> {
600 pub(crate) fn new(
601 desc_reg: &'r DescriptorRegistry,
602 ext_reg: &'r super::extension::registry::ExtensionRegistry,
603 bytes: &'a [u8],
604 inherited: Option<u32>,
605 ) -> Self {
606 Self {
607 desc_reg,
608 ext_reg,
609 bytes,
610 pos: 0,
611 fused: false,
612 current_pds: inherited,
613 }
614 }
615
616 #[must_use]
619 pub fn avs_scope(&self) -> Option<u32> {
620 self.current_pds
621 .filter(|p| *p == crate::descriptors::PDS_AVSA || *p == crate::descriptors::PDS_AVSV)
622 }
623}
624
625impl<'a> Iterator for ExtRegistryIter<'_, 'a> {
626 type Item = crate::Result<ExtIterItem<'a>>;
627
628 fn next(&mut self) -> Option<Self::Item> {
629 let (tag, full) = match crate::descriptors::any::next_loop_entry(
630 self.bytes,
631 &mut self.pos,
632 &mut self.fused,
633 )? {
634 Ok(v) => v,
635 Err(e) => return Some(Err(e)),
636 };
637
638 update_pds(&mut self.current_pds, tag, full);
639
640 let len = full.len() - 2;
641 if tag == crate::descriptors::extension::TAG && len >= 1 {
642 let tag_extension = full[2];
643 if self.ext_reg.has_custom(tag_extension) {
644 return Some(match self.ext_reg.parse_body(tag_extension, &full[3..]) {
645 Ok(super::extension::registry::RegisteredExtension::Custom {
646 tag_extension,
647 value,
648 }) => Ok(ExtIterItem::CustomExtension {
649 tag_extension,
650 value,
651 }),
652 Ok(super::extension::registry::RegisteredExtension::Builtin(d)) => {
653 Ok(ExtIterItem::Descriptor(AnyDescriptor::Extension(d)))
654 }
655 Err(e) => Err(e),
656 });
657 }
658 }
659
660 Some(
661 dispatch_entry(self.desc_reg, self.current_pds, tag, full).map(ExtIterItem::Descriptor),
662 )
663 }
664}
665
666impl core::iter::FusedIterator for ExtRegistryIter<'_, '_> {}
667
668#[cfg(test)]
669mod tests {
670 use super::*;
671 use crate::descriptors::private_data_specifier;
672 use crate::descriptors::private_data_specifier::{PDS_EACEM, PDS_NORDIG};
673 use crate::traits::DescriptorDef;
674
675 #[test]
676 fn pds_constants_match_the_register() {
677 assert_eq!(
680 private_data_specifier::private_data_specifier_name(PDS_EACEM),
681 Some("EACEM/EICTA")
682 );
683 assert_eq!(
684 private_data_specifier::private_data_specifier_name(PDS_NORDIG),
685 Some("NorDig")
686 );
687 }
688
689 #[derive(Debug, PartialEq, Eq)]
690 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
691 struct PdsEacem {
692 v: u8,
693 }
694
695 impl<'a> broadcast_common::Parse<'a> for PdsEacem {
696 type Error = crate::error::Error;
697 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
698 if bytes.len() < 3 {
699 return Err(crate::error::Error::BufferTooShort {
700 need: 3,
701 have: bytes.len(),
702 what: "PdsEacem",
703 });
704 }
705 Ok(Self { v: bytes[2] })
706 }
707 }
708
709 impl DescriptorDef<'_> for PdsEacem {
710 const TAG: u8 = 0x83;
711 const NAME: &'static str = "PDS_EACEM";
712 }
713
714 #[derive(Debug, PartialEq, Eq)]
715 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
716 struct PdsNordig {
717 w: u8,
718 }
719
720 impl<'a> broadcast_common::Parse<'a> for PdsNordig {
721 type Error = crate::error::Error;
722 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
723 if bytes.len() < 3 {
724 return Err(crate::error::Error::BufferTooShort {
725 need: 3,
726 have: bytes.len(),
727 what: "PdsNordig",
728 });
729 }
730 Ok(Self { w: bytes[2] })
731 }
732 }
733
734 impl DescriptorDef<'_> for PdsNordig {
735 const TAG: u8 = 0x83;
736 const NAME: &'static str = "PDS_NORDIG";
737 }
738
739 #[derive(Debug, PartialEq, Eq)]
740 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
741 struct PdsAgnostic {
742 z: u8,
743 }
744
745 impl<'a> broadcast_common::Parse<'a> for PdsAgnostic {
746 type Error = crate::error::Error;
747 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
748 if bytes.len() < 3 {
749 return Err(crate::error::Error::BufferTooShort {
750 need: 3,
751 have: bytes.len(),
752 what: "PdsAgnostic",
753 });
754 }
755 Ok(Self { z: bytes[2] })
756 }
757 }
758
759 impl DescriptorDef<'_> for PdsAgnostic {
760 const TAG: u8 = 0x84;
761 const NAME: &'static str = "PDS_AGNOSTIC";
762 }
763
764 fn pds_descriptor(pds: u32) -> Vec<u8> {
765 let mut v = vec![private_data_specifier::TAG, 4];
766 v.extend_from_slice(&pds.to_be_bytes());
767 v
768 }
769
770 #[test]
771 fn pds_scoped_same_tag_resolves_by_pds() {
772 let mut reg = DescriptorRegistry::new();
773 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
774 reg.register_for_pds::<PdsNordig>(PDS_NORDIG);
775
776 let mut bytes = Vec::new();
777 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
778 bytes.extend_from_slice(&[0x83, 0x01, 0xAA]);
779
780 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
781 assert_eq!(items.len(), 2);
782 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
783 match &items[1] {
784 AnyDescriptor::Other { tag, value } => {
785 assert_eq!(*tag, 0x83);
786 let c = value.downcast_ref::<PdsEacem>().unwrap();
787 assert_eq!(c.v, 0xAA);
788 }
789 other => panic!("expected Other (PdsEacem), got {other:?}"),
790 }
791
792 let mut bytes2 = Vec::new();
793 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
794 bytes2.extend_from_slice(&[0x83, 0x01, 0xBB]);
795
796 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
797 match &items2[1] {
798 AnyDescriptor::Other { tag, value } => {
799 assert_eq!(*tag, 0x83);
800 let c = value.downcast_ref::<PdsNordig>().unwrap();
801 assert_eq!(c.w, 0xBB);
802 }
803 other => panic!("expected Other (PdsNordig), got {other:?}"),
804 }
805 }
806
807 #[test]
808 fn pds_scoped_does_not_match_wrong_pds() {
809 let mut reg = DescriptorRegistry::new();
810 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
811
812 let mut bytes = Vec::new();
813 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
814 bytes.extend_from_slice(&[0x83, 0x01, 0xCC]);
815
816 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
817 assert_eq!(items.len(), 2);
818 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
819 match &items[1] {
820 AnyDescriptor::Unknown { tag, .. } => assert_eq!(*tag, 0x83),
821 other => panic!("expected Unknown (wrong PDS), got {other:?}"),
822 }
823 }
824
825 #[test]
828 fn avs2_and_tuwa_descriptors_are_scoped() {
829 use crate::descriptors::avs2_audio::Avs2AudioDescriptor;
830 use crate::descriptors::avs2_video::Avs2VideoDescriptor;
831 use crate::descriptors::private_data_specifier::{PDS_AVSA, PDS_AVSV};
832 use crate::descriptors::tuwa_avs3_video::TuwaAvs3VideoDescriptor;
833 let mut reg = DescriptorRegistry::new();
834 reg.with_avs2_video()
835 .with_avs2_audio()
836 .with_tuwa_avs3_video();
837
838 let v = [0x40, 5, 0x20, 0x42, 0x00, 0xA9, 0x5F];
839 let items: Vec<_> = reg.parse_loop(&v).collect::<Result<_, _>>().unwrap();
841 assert!(matches!(items[0], AnyDescriptor::NetworkName(_)));
842 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'V'];
844 b.extend_from_slice(&v);
845 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
846 match &items[1] {
847 AnyDescriptor::Other { tag: 0x40, value } => {
848 assert!(value.downcast_ref::<Avs2VideoDescriptor>().is_some());
849 }
850 other => panic!("expected Avs2Video, got {other:?}"),
851 }
852 let mut b = pds_descriptor(PDS_AVSV);
854 b.extend_from_slice(&v);
855 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
856 assert!(matches!(items[1], AnyDescriptor::Other { tag: 0x40, .. }));
857
858 let a = [0xD3, 2, 6, 0x20];
859 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'A'];
860 b.extend_from_slice(&a);
861 let items: Vec<_> = reg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
862 match &items[1] {
863 AnyDescriptor::Other { tag: 0xD3, value } => {
864 assert!(value.downcast_ref::<Avs2AudioDescriptor>().is_some());
865 }
866 other => panic!("expected Avs2Audio, got {other:?}"),
867 }
868 let mut b = pds_descriptor(PDS_AVSA);
869 b.extend_from_slice(&a);
870 assert!(matches!(
871 reg.parse_loop(&b).collect::<Result<Vec<_>, _>>().unwrap()[1],
872 AnyDescriptor::Other { tag: 0xD3, .. }
873 ));
874 let items: Vec<_> = reg.parse_loop(&a).collect::<Result<_, _>>().unwrap();
876 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD3, .. }));
877
878 let t = [62, 7, 0x22, 0x42, 0xAA, 0x4F, 9, 14, 9];
880 let items: Vec<_> = reg.parse_loop(&t).collect::<Result<_, _>>().unwrap();
881 match &items[0] {
882 AnyDescriptor::Other { tag: 62, value } => {
883 assert!(value.downcast_ref::<TuwaAvs3VideoDescriptor>().is_some());
884 }
885 other => panic!("expected TuwaAvs3Video, got {other:?}"),
886 }
887 let plain = DescriptorRegistry::new();
888 let items: Vec<_> = plain.parse_loop(&t).collect::<Result<_, _>>().unwrap();
889 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 62, .. }));
890 }
891
892 #[test]
897 fn program_info_registration_scopes_es_info_descriptors() {
898 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
899 use crate::descriptors::private_data_specifier::PDS_AVSV;
900 let program_info = [0x05, 4, b'A', b'V', b'S', b'V'];
901 let es_info = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
903 let mut reg = DescriptorRegistry::new();
904 reg.with_avs3_video();
905
906 let items: Vec<_> = reg.parse_loop(&es_info).collect::<Result<_, _>>().unwrap();
908 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD1, .. }));
909
910 let mut pi = reg.parse_loop(&program_info);
912 assert_eq!(pi.avs_scope(), None, "no entry consumed yet");
913 for item in pi.by_ref() {
914 item.unwrap();
915 }
916 let scope = pi.avs_scope();
917 assert_eq!(scope, Some(PDS_AVSV));
918 let items: Vec<_> = reg
919 .parse_loop_in_scope(&es_info, scope)
920 .collect::<Result<_, _>>()
921 .unwrap();
922 match &items[0] {
923 AnyDescriptor::Other { tag: 0xD1, value } => {
924 assert!(value.downcast_ref::<Avs3VideoDescriptor>().is_some());
925 }
926 other => panic!("expected Avs3Video via inherited scope, got {other:?}"),
927 }
928 let hevc = [0x05, 4, b'H', b'E', b'V', b'C'];
930 let mut pi = reg.parse_loop(&hevc);
931 for item in pi.by_ref() {
932 item.unwrap();
933 }
934 assert_eq!(pi.avs_scope(), None);
935 }
936
937 #[test]
940 fn avs3_video_descriptor_scopes() {
941 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
942 use crate::descriptors::private_data_specifier::PDS_AVSV;
943 let desc = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
944 let mut reg = DescriptorRegistry::new();
945 reg.with_avs3_video();
946 let check = |bytes: &[u8], idx: usize| {
947 let items: Vec<_> = reg.parse_loop(bytes).collect::<Result<_, _>>().unwrap();
948 match &items[idx] {
949 AnyDescriptor::Other { tag, value } => {
950 assert_eq!(*tag, 0xD1);
951 assert_eq!(
952 value
953 .downcast_ref::<Avs3VideoDescriptor>()
954 .unwrap()
955 .profile_id,
956 0x22
957 );
958 }
959 other => panic!("expected Other, got {other:?}"),
960 }
961 };
962 let mut pds = pds_descriptor(PDS_AVSV);
963 pds.extend_from_slice(&desc);
964 check(&pds, 1);
965 let mut registration = vec![0x05, 4, b'A', b'V', b'S', b'V'];
966 registration.extend_from_slice(&desc);
967 check(®istration, 1);
968 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
970 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD1, .. }));
971 let mut other = vec![0x05, 4, b'A', b'C', b'-', b'3'];
972 other.extend_from_slice(&desc);
973 let items: Vec<_> = reg.parse_loop(&other).collect::<Result<_, _>>().unwrap();
974 assert!(matches!(items[1], AnyDescriptor::Unknown { tag: 0xD1, .. }));
975 let adesc = [0xD2, 2, 0x72, 0x45];
977 let mut areg = DescriptorRegistry::new();
978 areg.with_avs3_audio();
979 let mut b = vec![0x05, 4, b'A', b'V', b'S', b'A'];
980 b.extend_from_slice(&adesc);
981 let items: Vec<_> = areg.parse_loop(&b).collect::<Result<_, _>>().unwrap();
982 assert!(matches!(items[1], AnyDescriptor::Other { tag: 0xD2, .. }));
983 }
984
985 #[test]
988 fn avs3_audio_descriptor_is_pds_scoped() {
989 use crate::descriptors::avs3_audio::Avs3AudioDescriptor;
990 use crate::descriptors::private_data_specifier::PDS_AVSA;
991 let desc = [0xD2, 6, 0x03, 0xAA, 0x95, 0x04, 0x00, 0x6A];
992 let mut reg = DescriptorRegistry::new();
993 reg.with_avs3_audio();
994
995 let mut bytes = Vec::new();
996 bytes.extend_from_slice(&pds_descriptor(PDS_AVSA));
997 bytes.extend_from_slice(&desc);
998 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
999 match &items[1] {
1000 AnyDescriptor::Other { tag, value } => {
1001 assert_eq!(*tag, 0xD2);
1002 let d = value.downcast_ref::<Avs3AudioDescriptor>().unwrap();
1003 assert_eq!(d.sampling_frequency_index, 3);
1004 }
1005 other => panic!("expected Other (Avs3AudioDescriptor), got {other:?}"),
1006 }
1007
1008 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1010 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0xD2, .. }));
1011 let mut other = Vec::new();
1012 other.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1013 other.extend_from_slice(&desc);
1014 let items: Vec<_> = reg.parse_loop(&other).collect::<Result<_, _>>().unwrap();
1015 assert!(matches!(items[1], AnyDescriptor::Unknown { tag: 0xD2, .. }));
1016 }
1017
1018 #[test]
1021 fn china_caption_service_is_opt_in() {
1022 use crate::descriptors::china_caption_service::ChinaCaptionServiceDescriptor;
1023 let desc = [
1024 0x86, 9, 0xE1, b'c', b'h', b'i', 0xC1, 0xC2, 0xFF, 0xE1, 0x00,
1025 ];
1026 let plain = DescriptorRegistry::new();
1027 let items: Vec<_> = plain.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1028 assert!(matches!(items[0], AnyDescriptor::Unknown { tag: 0x86, .. }));
1029 let mut reg = DescriptorRegistry::new();
1030 reg.with_china_caption_service();
1031 let items: Vec<_> = reg.parse_loop(&desc).collect::<Result<_, _>>().unwrap();
1032 match &items[0] {
1033 AnyDescriptor::Other { tag, value } => {
1034 assert_eq!(*tag, 0x86);
1035 let d = value
1036 .downcast_ref::<ChinaCaptionServiceDescriptor>()
1037 .unwrap();
1038 assert_eq!(d.services.len(), 1);
1039 }
1040 other => panic!("expected Other, got {other:?}"),
1041 }
1042 }
1043
1044 #[test]
1045 fn pds_agnostic_matches_without_pds() {
1046 let mut reg = DescriptorRegistry::new();
1047 reg.register::<PdsAgnostic>();
1048
1049 let bytes = [0x84, 0x01, 0xDD];
1050 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1051 assert_eq!(items.len(), 1);
1052 match &items[0] {
1053 AnyDescriptor::Other { tag, value } => {
1054 assert_eq!(*tag, 0x84);
1055 let c = value.downcast_ref::<PdsAgnostic>().unwrap();
1056 assert_eq!(c.z, 0xDD);
1057 }
1058 other => panic!("expected Other, got {other:?}"),
1059 }
1060 }
1061
1062 #[test]
1063 fn pds_scoped_takes_precedence_over_agnostic() {
1064 #[derive(Debug, PartialEq, Eq)]
1068 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
1069 struct Agnostic83 {
1070 a: u8,
1071 }
1072
1073 impl<'a> broadcast_common::Parse<'a> for Agnostic83 {
1074 type Error = crate::error::Error;
1075 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
1076 if bytes.len() < 3 {
1077 return Err(crate::error::Error::BufferTooShort {
1078 need: 3,
1079 have: bytes.len(),
1080 what: "Agnostic83",
1081 });
1082 }
1083 Ok(Self { a: bytes[2] })
1084 }
1085 }
1086
1087 impl DescriptorDef<'_> for Agnostic83 {
1088 const TAG: u8 = 0x83;
1089 const NAME: &'static str = "AGNOSTIC_83";
1090 }
1091
1092 let mut reg = DescriptorRegistry::new();
1093 reg.register::<Agnostic83>();
1094 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
1095
1096 let items: Vec<_> = reg
1098 .parse_loop(&[0x83, 0x01, 0xEE])
1099 .collect::<Result<_, _>>()
1100 .unwrap();
1101 match &items[0] {
1102 AnyDescriptor::Other { value, .. } => {
1103 assert!(value.downcast_ref::<Agnostic83>().is_some());
1104 assert!(value.downcast_ref::<PdsEacem>().is_none());
1105 }
1106 other => panic!("expected Other, got {other:?}"),
1107 }
1108
1109 let mut bytes = Vec::new();
1111 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1112 bytes.extend_from_slice(&[0x83, 0x01, 0xFF]);
1113 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1114 match &items[1] {
1115 AnyDescriptor::Other { value, .. } => {
1116 assert!(value.downcast_ref::<PdsEacem>().is_some());
1117 assert!(value.downcast_ref::<Agnostic83>().is_none());
1118 }
1119 other => panic!("expected Other, got {other:?}"),
1120 }
1121 }
1122
1123 fn logical_channel_descriptor(service_id: u16, visible: bool, lcn: u16) -> Vec<u8> {
1124 let mut v = vec![crate::descriptors::logical_channel::TAG, 4];
1126 v.extend_from_slice(&service_id.to_be_bytes());
1127 let flags = (u8::from(visible) << 7) | ((lcn >> 8) as u8 & 0x03);
1128 v.push(flags);
1129 v.push((lcn & 0xFF) as u8);
1130 v
1131 }
1132
1133 #[test]
1134 fn logical_channel_pds_scoped_matches_correct_pds() {
1135 let mut reg = DescriptorRegistry::new();
1136 reg.with_logical_channel_for_pds(PDS_EACEM);
1137
1138 let mut bytes = Vec::new();
1139 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1140 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
1141
1142 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1143 assert_eq!(items.len(), 2);
1144 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
1145 match &items[1] {
1146 AnyDescriptor::LogicalChannel(lc) => {
1147 assert_eq!(lc.entries.len(), 1);
1148 assert_eq!(lc.entries[0].service_id, 0x1234);
1149 assert!(lc.entries[0].visible_service);
1150 assert_eq!(lc.entries[0].logical_channel_number, 101);
1151 }
1152 other => panic!("expected LogicalChannel, got {other:?}"),
1153 }
1154 }
1155
1156 #[test]
1157 fn logical_channel_pds_scoped_rejects_no_pds() {
1158 let mut reg = DescriptorRegistry::new();
1159 reg.with_logical_channel_for_pds(PDS_EACEM);
1160
1161 let bytes = logical_channel_descriptor(0x1234, true, 101);
1162 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1163 assert_eq!(items.len(), 1);
1164 assert!(matches!(
1165 &items[0],
1166 AnyDescriptor::Unknown { tag: 0x83, .. }
1167 ));
1168 }
1169
1170 #[test]
1171 fn logical_channel_pds_scoped_rejects_wrong_pds() {
1172 let mut reg = DescriptorRegistry::new();
1173 reg.with_logical_channel_for_pds(PDS_EACEM);
1174
1175 let mut bytes = Vec::new();
1176 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1177 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
1178
1179 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1180 assert_eq!(items.len(), 2);
1181 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
1182 assert!(matches!(
1183 &items[1],
1184 AnyDescriptor::Unknown { tag: 0x83, .. }
1185 ));
1186 }
1187
1188 #[test]
1189 fn logical_channel_pds_scoped_multiple_pds() {
1190 let mut reg = DescriptorRegistry::new();
1191 reg.with_logical_channel_for_pds(PDS_EACEM);
1192 reg.with_logical_channel_for_pds(PDS_NORDIG);
1193
1194 let mut bytes = Vec::new();
1196 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
1197 bytes.extend_from_slice(&logical_channel_descriptor(0x0001, true, 1));
1198 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
1199 assert!(matches!(&items[1], AnyDescriptor::LogicalChannel(_)));
1200
1201 let mut bytes2 = Vec::new();
1203 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
1204 bytes2.extend_from_slice(&logical_channel_descriptor(0x0002, false, 2));
1205 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
1206 assert!(matches!(&items2[1], AnyDescriptor::LogicalChannel(_)));
1207 }
1208
1209 #[test]
1211 fn program_info_registration_scopes_es_info_with_extensions() {
1212 use crate::descriptors::any::DescriptorLoop;
1213 use crate::descriptors::avs3_video::Avs3VideoDescriptor;
1214 use crate::descriptors::extension::registry::ExtensionRegistry;
1215 use crate::descriptors::private_data_specifier::PDS_AVSV;
1216 let program_info = [0x05, 4, b'A', b'V', b'S', b'V'];
1217 let es_info = [0xD1, 8, 0x22, 0x42, 0xAA, 0x4B, 9, 14, 9, 0xFF];
1218 let mut reg = DescriptorRegistry::new();
1219 reg.with_avs3_video();
1220 let ext = ExtensionRegistry::new();
1221
1222 let items: Vec<_> = DescriptorLoop::new(&es_info)
1223 .iter_with_extensions(®, &ext)
1224 .collect::<Result<_, _>>()
1225 .unwrap();
1226 assert!(matches!(
1227 &items[0],
1228 ExtIterItem::Descriptor(AnyDescriptor::Unknown { tag: 0xD1, .. })
1229 ));
1230
1231 let mut pi = DescriptorLoop::new(&program_info).iter_with_extensions(®, &ext);
1232 for item in pi.by_ref() {
1233 item.unwrap();
1234 }
1235 let scope = pi.avs_scope();
1236 assert_eq!(scope, Some(PDS_AVSV));
1237 let items: Vec<_> = DescriptorLoop::new(&es_info)
1238 .iter_with_extensions_in_scope(®, &ext, scope)
1239 .collect::<Result<_, _>>()
1240 .unwrap();
1241 match &items[0] {
1242 ExtIterItem::Descriptor(AnyDescriptor::Other { tag: 0xD1, value }) => {
1243 assert!(value.downcast_ref::<Avs3VideoDescriptor>().is_some());
1244 }
1245 other => panic!("expected Avs3Video via inherited scope, got {other:?}"),
1246 }
1247 }
1248
1249 #[test]
1250 fn iter_with_extensions_surfaces_custom_extension() {
1251 use crate::descriptors::any::{AnyDescriptor, DescriptorLoop};
1252 use crate::descriptors::extension::registry::ExtensionRegistry;
1253
1254 #[derive(Debug, PartialEq, Eq)]
1255 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
1256 struct MyCustomExt {
1257 payload: Vec<u8>,
1258 }
1259
1260 impl<'a> broadcast_common::Parse<'a> for MyCustomExt {
1261 type Error = crate::error::Error;
1262 fn parse(sel: &'a [u8]) -> crate::Result<Self> {
1263 Ok(Self {
1264 payload: sel.to_vec(),
1265 })
1266 }
1267 }
1268
1269 impl crate::descriptors::extension::ExtensionBodyDef<'_> for MyCustomExt {
1270 const TAG_EXTENSION: u8 = 0x42;
1271 const NAME: &'static str = "MY_CUSTOM_EXT";
1272 }
1273
1274 let mut ext_reg = ExtensionRegistry::new();
1275 ext_reg.register::<MyCustomExt>();
1276
1277 let desc_reg = DescriptorRegistry::new();
1278
1279 let mut loop_bytes = vec![
1281 0x4D, 0x07, b'e', b'n', b'g', 0x02, b'H', b'i', 0x00, ];
1283 loop_bytes.extend_from_slice(&[0x7F, 0x03, 0x42, 0xAB, 0xCD]);
1285
1286 let dl = DescriptorLoop::new(&loop_bytes);
1287 let items: Vec<_> = dl
1288 .iter_with_extensions(&desc_reg, &ext_reg)
1289 .collect::<Result<_, _>>()
1290 .unwrap();
1291 assert_eq!(items.len(), 2);
1292 assert!(matches!(
1294 &items[0],
1295 ExtIterItem::Descriptor(AnyDescriptor::ShortEvent(_))
1296 ));
1297 match &items[1] {
1299 ExtIterItem::CustomExtension {
1300 tag_extension,
1301 value,
1302 } => {
1303 assert_eq!(*tag_extension, 0x42);
1304 let concrete = value.downcast_ref::<MyCustomExt>().unwrap();
1305 assert_eq!(concrete.payload, &[0xAB, 0xCD]);
1306 }
1307 other => panic!("expected CustomExtension, got {other:?}"),
1308 }
1309 }
1310}