pub mod rar_over_dvb_stream;
pub mod rar_over_ip;
pub mod scan;
pub use rar_over_dvb_stream::{RarDownloadSchedule, RarOverDvbStreamDescriptor};
pub use rar_over_ip::RarOverIpDescriptor;
pub use scan::{RntScanDescriptor, RntScanEntry};
use crate::descriptors::scoped::declare_scoped_namespace;
declare_scoped_namespace! {'a;
doc "Every crate-implemented RNT-specific descriptor (ETSI TS 102 323 Table 4: tags 0x40-0x42, which override their EN 300 468 meaning inside the RNT) plus the SI fall-through for every other tag.";
enum AnyRntDescriptor, iter RntDescriptorIter, loop RntDescriptorLoop, parse parse_rnt_loop;
RarOverDvbStream = 0x40 => crate::descriptors::rnt::rar_over_dvb_stream::RarOverDvbStreamDescriptor<'a>,
RarOverIp = 0x41 => crate::descriptors::rnt::rar_over_ip::RarOverIpDescriptor<'a>,
RntScan = 0x42 => crate::descriptors::rnt::scan::RntScanDescriptor<'a>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dispatched_tags_are_the_table_4_overrides() {
assert_eq!(AnyRntDescriptor::DISPATCHED_TAGS, &[0x40, 0x41, 0x42]);
}
#[test]
fn overrides_win_and_everything_else_is_si() {
let raw = [
0x42, 0x00, 0x48, 0x03, 0x01, 0x00, 0x00, 0x73, 0x03, b'a', b'b', b'c', ];
let items: Vec<_> = parse_rnt_loop(&raw).collect();
assert!(matches!(
items[0].as_ref().unwrap(),
AnyRntDescriptor::RntScan(_)
));
assert!(matches!(
items[1].as_ref().unwrap(),
AnyRntDescriptor::Si(_)
));
match items[2].as_ref().unwrap() {
AnyRntDescriptor::Si(d) => assert_eq!(d.name(), "DEFAULT_AUTHORITY"),
other => panic!("expected Si default_authority, got {other:?}"),
}
}
#[test]
fn mpeg_range_tags_are_si_not_unknown_in_rnt() {
let ok = [0x25, 0x05, 0x00, 0x10, 0x3F, 0x00, 0x7F];
match parse_rnt_loop(&ok).next().unwrap() {
Ok(AnyRntDescriptor::Si(d)) => assert_eq!(d.name(), "METADATA_POINTER"),
other => panic!("expected the typed SI path, got {other:?}"),
}
let empty = [0x25, 0x00];
match parse_rnt_loop(&empty).next().unwrap() {
Err(crate::Error::InvalidDescriptor { tag: 0x25, reason })
if reason.contains("metadata_pointer_descriptor too short") => {}
other => panic!("expected the SI parser's too-short error, got {other:?}"),
}
}
#[test]
fn loop_wrapper_and_truncation() {
let raw = [0x42, 0x00];
let l = RntDescriptorLoop::new(&raw);
assert_eq!(l.raw(), &raw[..]);
assert!(matches!(
l.iter().next().unwrap().unwrap(),
AnyRntDescriptor::RntScan(_)
));
let mut it = parse_rnt_loop(&[0x40, 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 = RntDescriptorLoop::new(&[0x42, 0x00]);
assert!(serde_json::to_string(&ok).unwrap().contains("rntScan"));
let bad = RntDescriptorLoop::new(&[0x40, 0xFF]);
assert!(serde_json::to_string(&bad).unwrap().contains("parseError"));
}
}