pub mod enhanced_message;
pub mod message;
pub mod scheduling;
pub mod ssu_event_name;
pub mod ssu_location;
pub mod ssu_uri;
pub mod subgroup_association;
pub mod update;
pub use enhanced_message::EnhancedMessageDescriptor;
pub use message::MessageDescriptor;
pub use scheduling::{SchedulingDescriptor, TimeUnit};
pub use ssu_event_name::SsuEventNameDescriptor;
pub use ssu_location::SsuLocationDescriptor;
pub use ssu_uri::SsuUriDescriptor;
pub use subgroup_association::SsuSubgroupAssociationDescriptor;
pub use update::{UpdateDescriptor, UpdateFlag, UpdateMethod};
use crate::descriptors::scoped::declare_scoped_namespace;
declare_scoped_namespace! {'a;
doc "Every crate-implemented UNT descriptor (ETSI TS 102 006 Table 19), the SI fall-through for tags `0x40..=0xFF`, and `Unknown` for an unimplemented tag in the UNT-owned `0x00..=0x3F` range.";
enum AnyUntDescriptor, iter UntDescriptorIter, loop UntDescriptorLoop, parse parse_unt_loop;
@owned 0x00..=0x3F,
Scheduling = 0x01 => crate::descriptors::unt::scheduling::SchedulingDescriptor<'a>,
Update = 0x02 => crate::descriptors::unt::update::UpdateDescriptor<'a>,
SsuLocation = 0x03 => crate::descriptors::unt::ssu_location::SsuLocationDescriptor<'a>,
Message = 0x04 => crate::descriptors::unt::message::MessageDescriptor<'a>,
SsuEventName = 0x05 => crate::descriptors::unt::ssu_event_name::SsuEventNameDescriptor<'a>,
TargetSmartcard = 0x06 => crate::descriptors::target::smartcard::TargetSmartcardDescriptor<'a>,
TargetMacAddress = 0x07 => crate::descriptors::target::mac_address::TargetMacAddressDescriptor<'a>,
TargetSerialNumber = 0x08 => crate::descriptors::target::serial_number::TargetSerialNumberDescriptor<'a>,
TargetIpAddress = 0x09 => crate::descriptors::target::ip_address::TargetIpAddressDescriptor<'a>,
TargetIpv6Address = 0x0A => crate::descriptors::target::ipv6_address::TargetIpv6AddressDescriptor<'a>,
SsuSubgroupAssociation = 0x0B => crate::descriptors::unt::subgroup_association::SsuSubgroupAssociationDescriptor,
EnhancedMessage = 0x0C => crate::descriptors::unt::enhanced_message::EnhancedMessageDescriptor<'a>,
SsuUri = 0x0D => crate::descriptors::unt::ssu_uri::SsuUriDescriptor<'a>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dispatched_tags_are_the_table_19_set() {
assert_eq!(
AnyUntDescriptor::DISPATCHED_TAGS,
&[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D
]
);
}
#[test]
fn unt_tags_do_not_decode_as_mpeg() {
let raw = [
0x02, 0x01, 0x01, 0x03, 0x02, 0x00, 0x05, 0x04, 0x04, 0x00, b'e', b'n', b'g', 0x0E, 0x00, ];
let items: Vec<_> = parse_unt_loop(&raw).collect();
assert!(matches!(
items[0].as_ref().unwrap(),
AnyUntDescriptor::Update(_)
));
assert!(matches!(
items[1].as_ref().unwrap(),
AnyUntDescriptor::SsuLocation(_)
));
assert!(matches!(
items[2].as_ref().unwrap(),
AnyUntDescriptor::Message(_)
));
assert!(matches!(
items[3].as_ref().unwrap(),
AnyUntDescriptor::Unknown { tag: 0x0E, .. }
));
}
#[test]
fn si_range_falls_back_to_si_dispatch() {
let raw = [0x5F, 0x04, 0x00, 0x00, 0x00, 0x28];
match parse_unt_loop(&raw).next().unwrap().unwrap() {
AnyUntDescriptor::Si(d) => assert_eq!(d.name(), "PRIVATE_DATA_SPECIFIER"),
other => panic!("expected Si, got {other:?}"),
}
}
#[test]
fn loop_wrapper_and_truncation() {
let raw = [0x0D, 0x02, 0x00, 0x00];
let l = UntDescriptorLoop::new(&raw);
assert_eq!(l.raw(), &raw[..]);
assert!(matches!(
l.iter().next().unwrap().unwrap(),
AnyUntDescriptor::SsuUri(_)
));
let mut it = parse_unt_loop(&[0x01, 0x20, 0x00]);
assert!(matches!(
&(it.next().unwrap()),
Err(crate::error::Error::BufferTooShort(..))
));
assert!(it.next().is_none());
}
#[cfg(feature = "serde")]
#[test]
fn serde_surfaces_typed_and_parse_errors() {
let ok = UntDescriptorLoop::new(&[0x0D, 0x02, 0x00, 0x00]);
assert!(serde_json::to_string(&ok).unwrap().contains("ssuUri"));
let bad = UntDescriptorLoop::new(&[0x01, 0xFF]);
assert!(serde_json::to_string(&bad).unwrap().contains("parseError"));
}
}