1use crate::descriptors::DescriptorRegistry;
2use crate::tables::bat;
3
4use super::{CompleteSectionSet, ParsedDescriptorLoop};
5
6#[derive(Debug)]
8#[non_exhaustive]
9pub struct CompleteBatTransportStream<'a> {
10 pub transport_stream_id: u16,
12 pub original_network_id: u16,
14 pub descriptors: ParsedDescriptorLoop<'a>,
16}
17
18#[derive(Debug)]
20#[non_exhaustive]
21pub struct CompleteBat<'a> {
22 pub bouquet_id: u16,
24 pub version_number: u8,
26 pub current_next_indicator: bool,
28 pub bouquet_descriptors: ParsedDescriptorLoop<'a>,
30 pub transport_streams: Vec<CompleteBatTransportStream<'a>>,
32}
33
34impl<'a> CompleteBat<'a> {
35 pub(crate) fn parse(
36 set: &'a CompleteSectionSet,
37 registry: Option<&'a DescriptorRegistry>,
38 ) -> crate::Result<Self> {
39 let sections: Vec<bat::BatSection<'a>> = set.parse_sections()?;
40 let first = sections.first().ok_or(crate::Error::BufferTooShort {
41 need: 1,
42 have: 0,
43 what: "CompleteBat sections",
44 })?;
45 let mut transport_streams = Vec::new();
46 for section in §ions {
47 transport_streams.extend(section.transport_streams.iter().map(|ts| {
48 CompleteBatTransportStream {
49 transport_stream_id: ts.transport_stream_id,
50 original_network_id: ts.original_network_id,
51 descriptors: ParsedDescriptorLoop::parse(ts.descriptors, registry),
52 }
53 }));
54 }
55 Ok(Self {
56 bouquet_id: first.bouquet_id,
57 version_number: first.version_number,
58 current_next_indicator: first.current_next_indicator,
59 bouquet_descriptors: ParsedDescriptorLoop::parse(first.bouquet_descriptors, registry),
60 transport_streams,
61 })
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::super::SectionSetCollector;
68 use crate::descriptors::DescriptorLoop;
69 use crate::tables::bat::BatSection;
70
71 fn build_bat_section(
72 bouquet_id: u16,
73 version: u8,
74 section_number: u8,
75 last_section_number: u8,
76 bouquet_desc: &[u8],
77 ts_entries: &[(u16, u16, &[u8])],
78 ) -> Vec<u8> {
79 use dvb_common::Serialize;
80 let bat = BatSection {
81 bouquet_id,
82 version_number: version,
83 current_next_indicator: true,
84 section_number,
85 last_section_number,
86 bouquet_descriptors: DescriptorLoop::new(bouquet_desc),
87 transport_streams: ts_entries
88 .iter()
89 .map(
90 |(tsid, onid, desc)| crate::tables::bat::BatTransportStream {
91 transport_stream_id: *tsid,
92 original_network_id: *onid,
93 descriptors: DescriptorLoop::new(desc),
94 },
95 )
96 .collect(),
97 };
98 let mut buf = vec![0u8; bat.serialized_len()];
99 bat.serialize_into(&mut buf).unwrap();
100 buf
101 }
102
103 #[test]
104 fn complete_bat_preserves_bouquet_descriptors_and_ts_entries() {
105 let bouquet_name = [0x47u8, 0x03, b'F', b'o', b'o'];
106 let ts_desc = [0x43u8, 0x01, 0x01];
107
108 let sec = build_bat_section(
109 0x1234,
110 3,
111 0,
112 0,
113 &bouquet_name,
114 &[(0x1001, 0x2002, &ts_desc)],
115 );
116
117 let mut collector = SectionSetCollector::new();
118 let set = collector.push_section(&sec).unwrap().unwrap();
119 let complete = set.bat().unwrap();
120
121 assert_eq!(complete.bouquet_id, 0x1234);
122 assert_eq!(complete.version_number, 3);
123 assert!(complete.current_next_indicator);
124 assert_eq!(complete.transport_streams.len(), 1);
125 assert_eq!(complete.transport_streams[0].transport_stream_id, 0x1001);
126 assert_eq!(complete.transport_streams[0].original_network_id, 0x2002);
127 }
128}