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