1use alloc::boxed::Box;
69use alloc::collections::BTreeMap;
70use core::any::Any;
71
72use crate::descriptors::any::AnyDescriptor;
73
74#[cfg(not(feature = "serde"))]
86pub trait DescriptorObject: core::fmt::Debug + Any + Send + Sync {
87 fn as_any(&self) -> &dyn Any;
89}
90
91#[cfg(feature = "serde")]
99pub trait DescriptorObject: core::fmt::Debug + Any + Send + Sync + erased_serde::Serialize {
100 fn as_any(&self) -> &dyn Any;
102}
103
104#[cfg(not(feature = "serde"))]
106impl<T> DescriptorObject for T
107where
108 T: core::fmt::Debug + Any + Send + Sync,
109{
110 fn as_any(&self) -> &dyn Any {
111 self
112 }
113}
114
115#[cfg(feature = "serde")]
117impl<T> DescriptorObject for T
118where
119 T: core::fmt::Debug + Any + Send + Sync + serde::Serialize,
120{
121 fn as_any(&self) -> &dyn Any {
122 self
123 }
124}
125
126impl dyn DescriptorObject {
138 #[must_use]
143 pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
144 self.as_any().downcast_ref::<T>()
145 }
146
147 #[must_use]
149 pub fn is<T: Any>(&self) -> bool {
150 self.as_any().is::<T>()
151 }
152}
153
154#[cfg(feature = "serde")]
166#[allow(clippy::borrowed_box)]
167pub(crate) fn serialize_erased<S: serde::Serializer>(
168 v: &Box<dyn DescriptorObject>,
169 s: S,
170) -> Result<S::Ok, S::Error> {
171 erased_serde::serialize(&**v, s)
172}
173
174pub(crate) type CustomParse =
181 Box<dyn for<'a> Fn(&'a [u8]) -> crate::Result<Box<dyn DescriptorObject>> + Send + Sync>;
182
183#[derive(Default)]
213pub struct DescriptorRegistry {
214 custom: BTreeMap<(Option<u32>, u8), CustomParse>,
215 logical_channel: bool,
216 logical_channel_pds: alloc::collections::BTreeSet<u32>,
217}
218
219impl DescriptorRegistry {
220 #[must_use]
222 pub fn new() -> Self {
223 Self::default()
224 }
225
226 pub fn register<T>(&mut self) -> &mut Self
247 where
248 T: for<'a> crate::traits::DescriptorDef<'a> + DescriptorObject + 'static,
249 {
250 let tag = <T as crate::traits::DescriptorDef<'static>>::TAG;
251 self.custom.insert(
252 (None, tag),
253 Box::new(|b| {
254 Ok(Box::new(<T as dvb_common::Parse>::parse(b)?) as Box<dyn DescriptorObject>)
255 }),
256 );
257 self
258 }
259
260 pub fn register_for_pds<T>(&mut self, pds: u32) -> &mut Self
272 where
273 T: for<'a> crate::traits::DescriptorDef<'a> + DescriptorObject + 'static,
274 {
275 let tag = <T as crate::traits::DescriptorDef<'static>>::TAG;
276 self.custom.insert(
277 (Some(pds), tag),
278 Box::new(|b| {
279 Ok(Box::new(<T as dvb_common::Parse>::parse(b)?) as Box<dyn DescriptorObject>)
280 }),
281 );
282 self
283 }
284
285 pub fn with_logical_channel(&mut self) -> &mut Self {
291 self.logical_channel = true;
292 self
293 }
294
295 pub fn with_logical_channel_for_pds(&mut self, pds: u32) -> &mut Self {
307 self.logical_channel_pds.insert(pds);
308 self
309 }
310
311 #[must_use]
321 pub fn parse_loop<'r, 'a>(&'r self, bytes: &'a [u8]) -> RegistryIter<'r, 'a> {
322 RegistryIter {
323 registry: self,
324 bytes,
325 pos: 0,
326 fused: false,
327 current_pds: None,
328 }
329 }
330}
331
332pub struct RegistryIter<'r, 'a> {
340 registry: &'r DescriptorRegistry,
341 bytes: &'a [u8],
342 pos: usize,
343 fused: bool,
344 current_pds: Option<u32>,
345}
346
347pub(crate) fn dispatch_entry<'a>(
353 registry: &DescriptorRegistry,
354 current_pds: Option<u32>,
355 tag: u8,
356 full: &'a [u8],
357) -> crate::Result<AnyDescriptor<'a>> {
358 if let Some(pds) = current_pds {
359 if let Some(parse_fn) = registry.custom.get(&(Some(pds), tag)) {
360 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
361 }
362 }
363 if let Some(parse_fn) = registry.custom.get(&(None, tag)) {
364 return parse_fn(full).map(|value| AnyDescriptor::Other { tag, value });
365 }
366 if let Some(pds) = current_pds {
367 if tag == crate::descriptors::logical_channel::TAG
368 && registry.logical_channel_pds.contains(&pds)
369 {
370 use dvb_common::Parse;
371 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
372 .map(AnyDescriptor::LogicalChannel);
373 }
374 }
375 if registry.logical_channel && tag == crate::descriptors::logical_channel::TAG {
376 use dvb_common::Parse;
377 return crate::descriptors::logical_channel::LogicalChannelDescriptor::parse(full)
378 .map(AnyDescriptor::LogicalChannel);
379 }
380 if let Some(res) = AnyDescriptor::dispatch(tag, full) {
381 return res;
382 }
383 Ok(AnyDescriptor::Unknown {
384 tag,
385 body: &full[2..],
386 })
387}
388
389fn update_pds(current: &mut Option<u32>, tag: u8, full: &[u8]) {
390 if tag == crate::descriptors::private_data_specifier::TAG {
391 use dvb_common::Parse;
392 if let Ok(pds) =
393 crate::descriptors::private_data_specifier::PrivateDataSpecifierDescriptor::parse(full)
394 {
395 *current = Some(pds.private_data_specifier);
396 }
397 }
398}
399
400impl<'r, 'a> Iterator for RegistryIter<'r, 'a> {
401 type Item = crate::Result<AnyDescriptor<'a>>;
402
403 fn next(&mut self) -> Option<Self::Item> {
404 let (tag, full) = match crate::descriptors::any::next_loop_entry(
405 self.bytes,
406 &mut self.pos,
407 &mut self.fused,
408 )? {
409 Ok(v) => v,
410 Err(e) => return Some(Err(e)),
411 };
412
413 update_pds(&mut self.current_pds, tag, full);
414
415 Some(dispatch_entry(self.registry, self.current_pds, tag, full))
416 }
417}
418
419impl core::iter::FusedIterator for RegistryIter<'_, '_> {}
420
421#[derive(Debug)]
433#[cfg_attr(feature = "serde", derive(serde::Serialize))]
434#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
435#[non_exhaustive]
436pub enum ExtIterItem<'a> {
437 Descriptor(AnyDescriptor<'a>),
439 CustomExtension {
441 tag_extension: u8,
443 #[cfg_attr(
446 feature = "serde",
447 serde(serialize_with = "super::extension::registry::serialize_erased")
448 )]
449 value: Box<dyn super::extension::registry::ExtensionObject>,
450 },
451}
452
453pub struct ExtRegistryIter<'r, 'a> {
463 desc_reg: &'r DescriptorRegistry,
464 ext_reg: &'r super::extension::registry::ExtensionRegistry,
465 bytes: &'a [u8],
466 pos: usize,
467 fused: bool,
468 current_pds: Option<u32>,
469}
470
471impl<'r, 'a> ExtRegistryIter<'r, 'a> {
472 pub(crate) fn new(
473 desc_reg: &'r DescriptorRegistry,
474 ext_reg: &'r super::extension::registry::ExtensionRegistry,
475 bytes: &'a [u8],
476 ) -> Self {
477 Self {
478 desc_reg,
479 ext_reg,
480 bytes,
481 pos: 0,
482 fused: false,
483 current_pds: None,
484 }
485 }
486}
487
488impl<'r, 'a> Iterator for ExtRegistryIter<'r, 'a> {
489 type Item = crate::Result<ExtIterItem<'a>>;
490
491 fn next(&mut self) -> Option<Self::Item> {
492 let (tag, full) = match crate::descriptors::any::next_loop_entry(
493 self.bytes,
494 &mut self.pos,
495 &mut self.fused,
496 )? {
497 Ok(v) => v,
498 Err(e) => return Some(Err(e)),
499 };
500
501 update_pds(&mut self.current_pds, tag, full);
502
503 let len = full.len() - 2;
504 if tag == crate::descriptors::extension::TAG && len >= 1 {
505 let tag_extension = full[2];
506 if self.ext_reg.has_custom(tag_extension) {
507 return Some(match self.ext_reg.parse_body(tag_extension, &full[3..]) {
508 Ok(super::extension::registry::RegisteredExtension::Custom {
509 tag_extension,
510 value,
511 }) => Ok(ExtIterItem::CustomExtension {
512 tag_extension,
513 value,
514 }),
515 Ok(super::extension::registry::RegisteredExtension::Builtin(d)) => {
516 Ok(ExtIterItem::Descriptor(AnyDescriptor::Extension(d)))
517 }
518 Err(e) => Err(e),
519 });
520 }
521 }
522
523 Some(
524 dispatch_entry(self.desc_reg, self.current_pds, tag, full).map(ExtIterItem::Descriptor),
525 )
526 }
527}
528
529impl core::iter::FusedIterator for ExtRegistryIter<'_, '_> {}
530
531#[cfg(test)]
532mod tests {
533 use super::*;
534 use crate::descriptors::private_data_specifier;
535 use crate::descriptors::private_data_specifier::{PDS_EACEM, PDS_NORDIG};
536 use crate::traits::DescriptorDef;
537
538 #[test]
539 fn pds_constants_match_the_register() {
540 assert_eq!(
543 private_data_specifier::private_data_specifier_name(PDS_EACEM),
544 Some("EACEM/EICTA")
545 );
546 assert_eq!(
547 private_data_specifier::private_data_specifier_name(PDS_NORDIG),
548 Some("NorDig")
549 );
550 }
551
552 #[derive(Debug, PartialEq, Eq)]
553 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
554 struct PdsEacem {
555 v: u8,
556 }
557
558 impl<'a> dvb_common::Parse<'a> for PdsEacem {
559 type Error = crate::error::Error;
560 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
561 if bytes.len() < 3 {
562 return Err(crate::error::Error::BufferTooShort {
563 need: 3,
564 have: bytes.len(),
565 what: "PdsEacem",
566 });
567 }
568 Ok(Self { v: bytes[2] })
569 }
570 }
571
572 impl<'a> DescriptorDef<'a> for PdsEacem {
573 const TAG: u8 = 0x83;
574 const NAME: &'static str = "PDS_EACEM";
575 }
576
577 #[derive(Debug, PartialEq, Eq)]
578 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
579 struct PdsNordig {
580 w: u8,
581 }
582
583 impl<'a> dvb_common::Parse<'a> for PdsNordig {
584 type Error = crate::error::Error;
585 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
586 if bytes.len() < 3 {
587 return Err(crate::error::Error::BufferTooShort {
588 need: 3,
589 have: bytes.len(),
590 what: "PdsNordig",
591 });
592 }
593 Ok(Self { w: bytes[2] })
594 }
595 }
596
597 impl<'a> DescriptorDef<'a> for PdsNordig {
598 const TAG: u8 = 0x83;
599 const NAME: &'static str = "PDS_NORDIG";
600 }
601
602 #[derive(Debug, PartialEq, Eq)]
603 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
604 struct PdsAgnostic {
605 z: u8,
606 }
607
608 impl<'a> dvb_common::Parse<'a> for PdsAgnostic {
609 type Error = crate::error::Error;
610 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
611 if bytes.len() < 3 {
612 return Err(crate::error::Error::BufferTooShort {
613 need: 3,
614 have: bytes.len(),
615 what: "PdsAgnostic",
616 });
617 }
618 Ok(Self { z: bytes[2] })
619 }
620 }
621
622 impl<'a> DescriptorDef<'a> for PdsAgnostic {
623 const TAG: u8 = 0x84;
624 const NAME: &'static str = "PDS_AGNOSTIC";
625 }
626
627 fn pds_descriptor(pds: u32) -> Vec<u8> {
628 let mut v = vec![private_data_specifier::TAG, 4];
629 v.extend_from_slice(&pds.to_be_bytes());
630 v
631 }
632
633 #[test]
634 fn pds_scoped_same_tag_resolves_by_pds() {
635 let mut reg = DescriptorRegistry::new();
636 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
637 reg.register_for_pds::<PdsNordig>(PDS_NORDIG);
638
639 let mut bytes = Vec::new();
640 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
641 bytes.extend_from_slice(&[0x83, 0x01, 0xAA]);
642
643 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
644 assert_eq!(items.len(), 2);
645 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
646 match &items[1] {
647 AnyDescriptor::Other { tag, value } => {
648 assert_eq!(*tag, 0x83);
649 let c = value.downcast_ref::<PdsEacem>().unwrap();
650 assert_eq!(c.v, 0xAA);
651 }
652 other => panic!("expected Other (PdsEacem), got {other:?}"),
653 }
654
655 let mut bytes2 = Vec::new();
656 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
657 bytes2.extend_from_slice(&[0x83, 0x01, 0xBB]);
658
659 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
660 match &items2[1] {
661 AnyDescriptor::Other { tag, value } => {
662 assert_eq!(*tag, 0x83);
663 let c = value.downcast_ref::<PdsNordig>().unwrap();
664 assert_eq!(c.w, 0xBB);
665 }
666 other => panic!("expected Other (PdsNordig), got {other:?}"),
667 }
668 }
669
670 #[test]
671 fn pds_scoped_does_not_match_wrong_pds() {
672 let mut reg = DescriptorRegistry::new();
673 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
674
675 let mut bytes = Vec::new();
676 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
677 bytes.extend_from_slice(&[0x83, 0x01, 0xCC]);
678
679 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
680 assert_eq!(items.len(), 2);
681 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
682 match &items[1] {
683 AnyDescriptor::Unknown { tag, .. } => assert_eq!(*tag, 0x83),
684 other => panic!("expected Unknown (wrong PDS), got {other:?}"),
685 }
686 }
687
688 #[test]
689 fn pds_agnostic_matches_without_pds() {
690 let mut reg = DescriptorRegistry::new();
691 reg.register::<PdsAgnostic>();
692
693 let bytes = [0x84, 0x01, 0xDD];
694 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
695 assert_eq!(items.len(), 1);
696 match &items[0] {
697 AnyDescriptor::Other { tag, value } => {
698 assert_eq!(*tag, 0x84);
699 let c = value.downcast_ref::<PdsAgnostic>().unwrap();
700 assert_eq!(c.z, 0xDD);
701 }
702 other => panic!("expected Other, got {other:?}"),
703 }
704 }
705
706 #[test]
707 fn pds_scoped_takes_precedence_over_agnostic() {
708 #[derive(Debug, PartialEq, Eq)]
712 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
713 struct Agnostic83 {
714 a: u8,
715 }
716
717 impl<'a> dvb_common::Parse<'a> for Agnostic83 {
718 type Error = crate::error::Error;
719 fn parse(bytes: &'a [u8]) -> crate::Result<Self> {
720 if bytes.len() < 3 {
721 return Err(crate::error::Error::BufferTooShort {
722 need: 3,
723 have: bytes.len(),
724 what: "Agnostic83",
725 });
726 }
727 Ok(Self { a: bytes[2] })
728 }
729 }
730
731 impl<'a> DescriptorDef<'a> for Agnostic83 {
732 const TAG: u8 = 0x83;
733 const NAME: &'static str = "AGNOSTIC_83";
734 }
735
736 let mut reg = DescriptorRegistry::new();
737 reg.register::<Agnostic83>();
738 reg.register_for_pds::<PdsEacem>(PDS_EACEM);
739
740 let items: Vec<_> = reg
742 .parse_loop(&[0x83, 0x01, 0xEE])
743 .collect::<Result<_, _>>()
744 .unwrap();
745 match &items[0] {
746 AnyDescriptor::Other { value, .. } => {
747 assert!(value.downcast_ref::<Agnostic83>().is_some());
748 assert!(value.downcast_ref::<PdsEacem>().is_none());
749 }
750 other => panic!("expected Other, got {other:?}"),
751 }
752
753 let mut bytes = Vec::new();
755 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
756 bytes.extend_from_slice(&[0x83, 0x01, 0xFF]);
757 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
758 match &items[1] {
759 AnyDescriptor::Other { value, .. } => {
760 assert!(value.downcast_ref::<PdsEacem>().is_some());
761 assert!(value.downcast_ref::<Agnostic83>().is_none());
762 }
763 other => panic!("expected Other, got {other:?}"),
764 }
765 }
766
767 fn logical_channel_descriptor(service_id: u16, visible: bool, lcn: u16) -> Vec<u8> {
768 let mut v = vec![crate::descriptors::logical_channel::TAG, 4];
770 v.extend_from_slice(&service_id.to_be_bytes());
771 let flags = (u8::from(visible) << 7) | ((lcn >> 8) as u8 & 0x03);
772 v.push(flags);
773 v.push((lcn & 0xFF) as u8);
774 v
775 }
776
777 #[test]
778 fn logical_channel_pds_scoped_matches_correct_pds() {
779 let mut reg = DescriptorRegistry::new();
780 reg.with_logical_channel_for_pds(PDS_EACEM);
781
782 let mut bytes = Vec::new();
783 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
784 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
785
786 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
787 assert_eq!(items.len(), 2);
788 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
789 match &items[1] {
790 AnyDescriptor::LogicalChannel(lc) => {
791 assert_eq!(lc.entries.len(), 1);
792 assert_eq!(lc.entries[0].service_id, 0x1234);
793 assert!(lc.entries[0].visible_service);
794 assert_eq!(lc.entries[0].logical_channel_number, 101);
795 }
796 other => panic!("expected LogicalChannel, got {other:?}"),
797 }
798 }
799
800 #[test]
801 fn logical_channel_pds_scoped_rejects_no_pds() {
802 let mut reg = DescriptorRegistry::new();
803 reg.with_logical_channel_for_pds(PDS_EACEM);
804
805 let bytes = logical_channel_descriptor(0x1234, true, 101);
806 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
807 assert_eq!(items.len(), 1);
808 assert!(matches!(
809 &items[0],
810 AnyDescriptor::Unknown { tag: 0x83, .. }
811 ));
812 }
813
814 #[test]
815 fn logical_channel_pds_scoped_rejects_wrong_pds() {
816 let mut reg = DescriptorRegistry::new();
817 reg.with_logical_channel_for_pds(PDS_EACEM);
818
819 let mut bytes = Vec::new();
820 bytes.extend_from_slice(&pds_descriptor(PDS_NORDIG));
821 bytes.extend_from_slice(&logical_channel_descriptor(0x1234, true, 101));
822
823 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
824 assert_eq!(items.len(), 2);
825 assert!(matches!(items[0], AnyDescriptor::PrivateDataSpecifier(_)));
826 assert!(matches!(
827 &items[1],
828 AnyDescriptor::Unknown { tag: 0x83, .. }
829 ));
830 }
831
832 #[test]
833 fn logical_channel_pds_scoped_multiple_pds() {
834 let mut reg = DescriptorRegistry::new();
835 reg.with_logical_channel_for_pds(PDS_EACEM);
836 reg.with_logical_channel_for_pds(PDS_NORDIG);
837
838 let mut bytes = Vec::new();
840 bytes.extend_from_slice(&pds_descriptor(PDS_EACEM));
841 bytes.extend_from_slice(&logical_channel_descriptor(0x0001, true, 1));
842 let items: Vec<_> = reg.parse_loop(&bytes).collect::<Result<_, _>>().unwrap();
843 assert!(matches!(&items[1], AnyDescriptor::LogicalChannel(_)));
844
845 let mut bytes2 = Vec::new();
847 bytes2.extend_from_slice(&pds_descriptor(PDS_NORDIG));
848 bytes2.extend_from_slice(&logical_channel_descriptor(0x0002, false, 2));
849 let items2: Vec<_> = reg.parse_loop(&bytes2).collect::<Result<_, _>>().unwrap();
850 assert!(matches!(&items2[1], AnyDescriptor::LogicalChannel(_)));
851 }
852
853 #[test]
854 fn iter_with_extensions_surfaces_custom_extension() {
855 use crate::descriptors::any::{AnyDescriptor, DescriptorLoop};
856 use crate::descriptors::extension::registry::ExtensionRegistry;
857
858 #[derive(Debug, PartialEq, Eq)]
859 #[cfg_attr(feature = "serde", derive(serde::Serialize))]
860 struct MyCustomExt {
861 payload: Vec<u8>,
862 }
863
864 impl<'a> dvb_common::Parse<'a> for MyCustomExt {
865 type Error = crate::error::Error;
866 fn parse(sel: &'a [u8]) -> crate::Result<Self> {
867 Ok(Self {
868 payload: sel.to_vec(),
869 })
870 }
871 }
872
873 impl<'a> crate::descriptors::extension::ExtensionBodyDef<'a> for MyCustomExt {
874 const TAG_EXTENSION: u8 = 0x42;
875 const NAME: &'static str = "MY_CUSTOM_EXT";
876 }
877
878 let mut ext_reg = ExtensionRegistry::new();
879 ext_reg.register::<MyCustomExt>();
880
881 let desc_reg = DescriptorRegistry::new();
882
883 let mut loop_bytes = vec![
885 0x4D, 0x07, b'e', b'n', b'g', 0x02, b'H', b'i', 0x00, ];
887 loop_bytes.extend_from_slice(&[0x7F, 0x03, 0x42, 0xAB, 0xCD]);
889
890 let dl = DescriptorLoop::new(&loop_bytes);
891 let items: Vec<_> = dl
892 .iter_with_extensions(&desc_reg, &ext_reg)
893 .collect::<Result<_, _>>()
894 .unwrap();
895 assert_eq!(items.len(), 2);
896 assert!(matches!(
898 &items[0],
899 ExtIterItem::Descriptor(AnyDescriptor::ShortEvent(_))
900 ));
901 match &items[1] {
903 ExtIterItem::CustomExtension {
904 tag_extension,
905 value,
906 } => {
907 assert_eq!(*tag_extension, 0x42);
908 let concrete = value.downcast_ref::<MyCustomExt>().unwrap();
909 assert_eq!(concrete.payload, &[0xAB, 0xCD]);
910 }
911 other => panic!("expected CustomExtension, got {other:?}"),
912 }
913 }
914}