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