pub mod generic_stream_location;
pub mod isp_access_mode;
pub mod platform_name;
pub mod platform_provider_name;
pub mod stream_location;
pub mod target_ip_slash;
pub mod target_ip_source_slash;
pub mod target_ipv6_slash;
pub mod target_ipv6_source_slash;
pub mod target_mac_address_range;
pub use generic_stream_location::{
GenericStreamSelector, IpMacGenericStreamLocationDescriptor, ModulationSystemType, PhyStreamId,
};
pub use isp_access_mode::{IspAccessMode, IspAccessModeDescriptor};
pub use platform_name::IpMacPlatformNameDescriptor;
pub use platform_provider_name::IpMacPlatformProviderNameDescriptor;
pub use stream_location::IpMacStreamLocationDescriptor;
pub use target_ip_slash::{Ipv4Slash, TargetIpSlashDescriptor};
pub use target_ip_source_slash::{Ipv4SourceDestSlash, TargetIpSourceSlashDescriptor};
pub use target_ipv6_slash::{Ipv6Slash, TargetIpv6SlashDescriptor};
pub use target_ipv6_source_slash::{Ipv6SourceDestSlash, TargetIpv6SourceSlashDescriptor};
pub use target_mac_address_range::{MacAddressRange, TargetMacAddressRangeDescriptor};
use crate::descriptors::scoped::declare_scoped_namespace;
declare_scoped_namespace! {'a;
doc "Every crate-implemented INT descriptor (ETSI EN 301 192 Table 19), the SI fall-through for tags `0x40..=0xFF`, and `Unknown` for an unimplemented tag in the INT-owned `0x00..=0x3F` range.";
enum AnyIntDescriptor, iter IntDescriptorIter, loop IntDescriptorLoop, parse parse_int_loop;
@owned 0x00..=0x3F,
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>,
IpMacPlatformName = 0x0C => crate::descriptors::int::platform_name::IpMacPlatformNameDescriptor<'a>,
IpMacPlatformProviderName = 0x0D => crate::descriptors::int::platform_provider_name::IpMacPlatformProviderNameDescriptor<'a>,
TargetMacAddressRange = 0x0E => crate::descriptors::int::target_mac_address_range::TargetMacAddressRangeDescriptor<'a>,
TargetIpSlash = 0x0F => crate::descriptors::int::target_ip_slash::TargetIpSlashDescriptor<'a>,
TargetIpSourceSlash = 0x10 => crate::descriptors::int::target_ip_source_slash::TargetIpSourceSlashDescriptor<'a>,
TargetIpv6Slash = 0x11 => crate::descriptors::int::target_ipv6_slash::TargetIpv6SlashDescriptor<'a>,
TargetIpv6SourceSlash = 0x12 => crate::descriptors::int::target_ipv6_source_slash::TargetIpv6SourceSlashDescriptor<'a>,
IpMacStreamLocation = 0x13 => crate::descriptors::int::stream_location::IpMacStreamLocationDescriptor<'a>,
IspAccessMode = 0x14 => crate::descriptors::int::isp_access_mode::IspAccessModeDescriptor<'a>,
IpMacGenericStreamLocation = 0x15 => crate::descriptors::int::generic_stream_location::IpMacGenericStreamLocationDescriptor<'a>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dispatched_tags_are_the_table_19_set() {
assert_eq!(
AnyIntDescriptor::DISPATCHED_TAGS,
&[
0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15
]
);
}
#[test]
fn mpeg_range_is_not_decoded_as_si() {
let raw = [
0x09, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0x00, 0x25, 0x01, 0xAA, ];
let items: Vec<_> = parse_int_loop(&raw).collect();
assert!(matches!(
items[0].as_ref().unwrap(),
AnyIntDescriptor::TargetIpAddress(_)
));
assert!(matches!(
items[1].as_ref().unwrap(),
AnyIntDescriptor::Unknown { tag: 0x0B, .. }
));
assert!(matches!(
items[2].as_ref().unwrap(),
AnyIntDescriptor::Unknown { tag: 0x25, .. }
));
}
#[test]
fn si_range_falls_back_to_si_dispatch() {
let raw = [0x57, 0x03, 0x00, 0x00, 0x00];
let item = parse_int_loop(&raw).next().unwrap().unwrap();
match item {
AnyIntDescriptor::Si(d) => assert_eq!(d.name(), "TELEPHONE"),
other => panic!("expected Si, got {other:?}"),
}
}
#[test]
fn loop_wrapper_iter_raw_and_truncation() {
let raw = [0x14, 0x01, 0x01];
let l = IntDescriptorLoop::new(&raw);
assert_eq!(l.raw(), &raw[..]);
assert!(matches!(
l.iter().next().unwrap().unwrap(),
AnyIntDescriptor::IspAccessMode(_)
));
let bad = [0x14, 0x05, 0x01];
let mut it = parse_int_loop(&bad);
assert!(matches!(
it.next().unwrap(),
Err(crate::Error::BufferTooShort(..))
));
assert!(it.next().is_none());
}
#[cfg(feature = "serde")]
#[test]
fn serde_surfaces_typed_and_parse_errors() {
let ok = IntDescriptorLoop::new(&[0x14, 0x01, 0x01]);
let json = serde_json::to_string(&ok).unwrap();
assert!(
json.contains("ispAccessMode") && json.contains("Dialup"),
"{json}"
);
let bad = IntDescriptorLoop::new(&[0x14, 0xFF]);
assert!(serde_json::to_string(&bad).unwrap().contains("parseError"));
}
}