1use super::*;
3
4impl<'a> ExtensionBodyDef<'a> for T2DeliverySystem {
5 const TAG_EXTENSION: u8 = 0x04;
6 const NAME: &'static str = "T2_DELIVERY_SYSTEM";
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize))]
12pub struct T2Cell {
13 pub cell_id: u16,
15 pub centre_frequencies: Vec<u32>,
18 pub subcells: Vec<T2Subcell>,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize))]
25pub struct T2Subcell {
26 pub cell_id_extension: u8,
28 pub transposer_frequency: u32,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize))]
35pub struct T2DeliverySystem {
36 pub plp_id: u8,
38 pub t2_system_id: u16,
40 pub siso_miso: Option<u8>,
42 pub bandwidth: Option<u8>,
44 pub guard_interval: Option<u8>,
46 pub transmission_mode: Option<u8>,
48 pub other_frequency_flag: Option<bool>,
50 pub tfs_flag: Option<bool>,
52 pub cells: Vec<T2Cell>,
54}
55
56impl<'a> Parse<'a> for T2DeliverySystem {
57 type Error = crate::error::Error;
58 fn parse(sel: &'a [u8]) -> Result<Self> {
59 if sel.len() < T2_FIXED_PREFIX_LEN {
60 return Err(Error::BufferTooShort {
61 need: T2_FIXED_PREFIX_LEN,
62 have: sel.len(),
63 what: "T2_delivery_system body",
64 });
65 }
66 let plp_id = sel[0];
67 let t2_system_id = u16::from_be_bytes([sel[1], sel[2]]);
68 let mut pos = T2_FIXED_PREFIX_LEN;
69 let (
70 siso_miso,
71 bandwidth,
72 guard_interval,
73 transmission_mode,
74 other_frequency_flag,
75 tfs_flag,
76 ) = if sel.len() > T2_FIXED_PREFIX_LEN {
77 if sel.len() < T2_FIXED_PREFIX_LEN + T2_FLAGS_BLOCK_LEN {
78 return Err(Error::BufferTooShort {
79 need: T2_FIXED_PREFIX_LEN + T2_FLAGS_BLOCK_LEN,
80 have: sel.len(),
81 what: "T2_delivery_system body",
82 });
83 }
84 let b0 = sel[pos];
85 let b1 = sel[pos + 1];
86 pos += T2_FLAGS_BLOCK_LEN;
87 (
88 Some(b0 >> 6),
89 Some((b0 >> 2) & 0x0F),
90 Some(b1 >> 5),
91 Some((b1 >> 2) & 0x07),
92 Some((b1 & 0x02) != 0),
93 Some((b1 & 0x01) != 0),
94 )
95 } else {
96 (None, None, None, None, None, None)
97 };
98 let cells = if siso_miso.is_some() {
99 let tfs = tfs_flag.unwrap();
100 let mut cells = Vec::new();
101 while pos < sel.len() {
102 if pos + 2 > sel.len() {
103 return Err(Error::BufferTooShort {
104 need: pos + 2,
105 have: sel.len(),
106 what: "T2_delivery_system body",
107 });
108 }
109 let cell_id = u16::from_be_bytes([sel[pos], sel[pos + 1]]);
110 pos += 2;
111 let centre_frequencies = if tfs {
112 if pos >= sel.len() {
113 return Err(Error::BufferTooShort {
114 need: pos + 1,
115 have: sel.len(),
116 what: "T2_delivery_system body",
117 });
118 }
119 let freq_loop_len = sel[pos] as usize;
120 pos += 1;
121 if freq_loop_len % 4 != 0 {
122 return Err(invalid(
123 "T2_delivery_system: frequency_loop_length not a multiple of 4",
124 ));
125 }
126 if pos + freq_loop_len > sel.len() {
127 return Err(Error::BufferTooShort {
128 need: pos + freq_loop_len,
129 have: sel.len(),
130 what: "T2_delivery_system body",
131 });
132 }
133 let end = pos + freq_loop_len;
134 let mut freqs = Vec::with_capacity(freq_loop_len / 4);
135 while pos < end {
136 freqs.push(u32::from_be_bytes([
137 sel[pos],
138 sel[pos + 1],
139 sel[pos + 2],
140 sel[pos + 3],
141 ]));
142 pos += 4;
143 }
144 freqs
145 } else {
146 if pos + 4 > sel.len() {
147 return Err(Error::BufferTooShort {
148 need: pos + 4,
149 have: sel.len(),
150 what: "T2_delivery_system body",
151 });
152 }
153 let freq =
154 u32::from_be_bytes([sel[pos], sel[pos + 1], sel[pos + 2], sel[pos + 3]]);
155 pos += 4;
156 vec![freq]
157 };
158 if pos >= sel.len() {
159 return Err(Error::BufferTooShort {
160 need: pos + 1,
161 have: sel.len(),
162 what: "T2_delivery_system body",
163 });
164 }
165 let subcell_loop_len = sel[pos] as usize;
166 pos += 1;
167 if subcell_loop_len % 5 != 0 {
168 return Err(invalid(
169 "T2_delivery_system: subcell_info_loop_length not a multiple of 5",
170 ));
171 }
172 if pos + subcell_loop_len > sel.len() {
173 return Err(Error::BufferTooShort {
174 need: pos + subcell_loop_len,
175 have: sel.len(),
176 what: "T2_delivery_system body",
177 });
178 }
179 let end = pos + subcell_loop_len;
180 let mut subcells = Vec::with_capacity(subcell_loop_len / 5);
181 while pos < end {
182 subcells.push(T2Subcell {
183 cell_id_extension: sel[pos],
184 transposer_frequency: u32::from_be_bytes([
185 sel[pos + 1],
186 sel[pos + 2],
187 sel[pos + 3],
188 sel[pos + 4],
189 ]),
190 });
191 pos += 5;
192 }
193 cells.push(T2Cell {
194 cell_id,
195 centre_frequencies,
196 subcells,
197 });
198 }
199 cells
200 } else {
201 Vec::new()
202 };
203 Ok(T2DeliverySystem {
204 plp_id,
205 t2_system_id,
206 siso_miso,
207 bandwidth,
208 guard_interval,
209 transmission_mode,
210 other_frequency_flag,
211 tfs_flag,
212 cells,
213 })
214 }
215}
216
217impl Serialize for T2DeliverySystem {
218 type Error = crate::error::Error;
219 fn serialized_len(&self) -> usize {
220 let mut len = T2_FIXED_PREFIX_LEN;
221 if self.siso_miso.is_some() {
222 len += T2_FLAGS_BLOCK_LEN;
223 let tfs = self.tfs_flag.unwrap_or(false);
224 for cell in &self.cells {
225 len += 2; if tfs {
227 len += 1 + cell.centre_frequencies.len() * 4;
228 } else {
229 len += 4;
230 }
231 len += 1 + cell.subcells.len() * 5;
232 }
233 }
234 len
235 }
236 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
237 let len = self.serialized_len();
238 if buf.len() < len {
239 return Err(Error::OutputBufferTooSmall {
240 need: len,
241 have: buf.len(),
242 });
243 }
244 buf[0] = self.plp_id;
245 buf[1..3].copy_from_slice(&self.t2_system_id.to_be_bytes());
246 let mut p = T2_FIXED_PREFIX_LEN;
247 if let (Some(sm), Some(bw), Some(gi), Some(tm), Some(off), Some(tfs)) = (
248 self.siso_miso,
249 self.bandwidth,
250 self.guard_interval,
251 self.transmission_mode,
252 self.other_frequency_flag,
253 self.tfs_flag,
254 ) {
255 buf[p] = (sm << 6) | ((bw & 0x0F) << 2) | 0x03;
256 buf[p + 1] = (gi << 5) | ((tm & 0x07) << 2) | (u8::from(off) << 1) | u8::from(tfs);
257 p += T2_FLAGS_BLOCK_LEN;
258 for cell in &self.cells {
259 buf[p..p + 2].copy_from_slice(&cell.cell_id.to_be_bytes());
260 p += 2;
261 if tfs {
262 let freq_len = (cell.centre_frequencies.len() * 4) as u8;
263 buf[p] = freq_len;
264 p += 1;
265 for &freq in &cell.centre_frequencies {
266 buf[p..p + 4].copy_from_slice(&freq.to_be_bytes());
267 p += 4;
268 }
269 } else {
270 let freq = cell.centre_frequencies.first().copied().unwrap_or(0);
271 buf[p..p + 4].copy_from_slice(&freq.to_be_bytes());
272 p += 4;
273 }
274 let subcell_len = (cell.subcells.len() * 5) as u8;
275 buf[p] = subcell_len;
276 p += 1;
277 for sc in &cell.subcells {
278 buf[p] = sc.cell_id_extension;
279 buf[p + 1..p + 5].copy_from_slice(&sc.transposer_frequency.to_be_bytes());
280 p += 5;
281 }
282 }
283 }
284 Ok(len)
285 }
286}
287
288#[cfg(test)]
289mod tests {
290 use super::*;
291 use crate::descriptors::extension::test_support::*;
292 use crate::descriptors::extension::{ExtensionBody, ExtensionDescriptor};
293
294 #[test]
295 fn parse_t2_minimal() {
296 let sel = [0x07, 0x12, 0x34];
298 let bytes = wrap(0x04, &sel);
299 let d = ExtensionDescriptor::parse(&bytes).unwrap();
300 match &d.body {
301 ExtensionBody::T2DeliverySystem(b) => {
302 assert_eq!(b.plp_id, 0x07);
303 assert_eq!(b.t2_system_id, 0x1234);
304 assert_eq!(b.siso_miso, None);
305 assert!(b.cells.is_empty());
306 }
307 other => panic!("expected T2DeliverySystem, got {other:?}"),
308 }
309 round_trip(&d);
310 }
311
312 #[test]
313 fn parse_t2_structured_flags_and_cells() {
314 let b0: u8 = ((0x04 & 0x0F) << 2) | 0x03; let b1: u8 = (0x06 << 5) | ((0x03 & 0x07) << 2) | (u8::from(false) << 1) | u8::from(true);
318 let cell1 = [0x12, 0x34, 0x00, 0x00];
320 let f1 = 0x01020304u32;
322 let f2 = 0x05060708u32;
323 let f3 = 0x090A0B0Cu32;
324 let sc1_id = 0x10u8;
325 let sc1_freq = 0x11121314u32;
326 let sc2_id = 0x20u8;
327 let sc2_freq = 0x21222324u32;
328 let mut cell2 = Vec::new();
329 cell2.extend_from_slice(&0x5678u16.to_be_bytes());
330 cell2.push(12);
331 cell2.extend_from_slice(&f1.to_be_bytes());
332 cell2.extend_from_slice(&f2.to_be_bytes());
333 cell2.extend_from_slice(&f3.to_be_bytes());
334 cell2.push(10);
335 cell2.push(sc1_id);
336 cell2.extend_from_slice(&sc1_freq.to_be_bytes());
337 cell2.push(sc2_id);
338 cell2.extend_from_slice(&sc2_freq.to_be_bytes());
339 let mut sel = vec![0x07, 0x12, 0x34, b0, b1];
340 sel.extend_from_slice(&cell1);
341 sel.extend_from_slice(&cell2);
342 let bytes = wrap(0x04, &sel);
343 let d = ExtensionDescriptor::parse(&bytes).unwrap();
344 match &d.body {
345 ExtensionBody::T2DeliverySystem(b) => {
346 assert_eq!(b.plp_id, 0x07);
347 assert_eq!(b.t2_system_id, 0x1234);
348 assert_eq!(b.siso_miso, Some(0x00));
349 assert_eq!(b.bandwidth, Some(0x04));
350 assert_eq!(b.guard_interval, Some(0x06));
351 assert_eq!(b.transmission_mode, Some(0x03));
352 assert_eq!(b.other_frequency_flag, Some(false));
353 assert_eq!(b.tfs_flag, Some(true));
354 assert_eq!(b.cells.len(), 2);
355 assert_eq!(b.cells[0].cell_id, 0x1234);
357 assert!(b.cells[0].centre_frequencies.is_empty());
358 assert!(b.cells[0].subcells.is_empty());
359 assert_eq!(b.cells[1].cell_id, 0x5678);
361 assert_eq!(b.cells[1].centre_frequencies, vec![f1, f2, f3]);
362 assert_eq!(b.cells[1].subcells.len(), 2);
363 assert_eq!(b.cells[1].subcells[0].cell_id_extension, sc1_id);
364 assert_eq!(b.cells[1].subcells[0].transposer_frequency, sc1_freq);
365 assert_eq!(b.cells[1].subcells[1].cell_id_extension, sc2_id);
366 assert_eq!(b.cells[1].subcells[1].transposer_frequency, sc2_freq);
367 }
368 other => panic!("expected T2DeliverySystem, got {other:?}"),
369 }
370 round_trip(&d);
371 }
372
373 #[test]
374 fn tsduck_t2_reference() {
375 let bytes = from_hex(
376 "7f240456789a13cd12340000678a0c075bcd1505e30a780fd22c320a1217ea6406fa0aa9fc59",
377 );
378 let d = ExtensionDescriptor::parse(&bytes).unwrap();
379 match &d.body {
380 ExtensionBody::T2DeliverySystem(b) => {
381 assert_eq!(b.plp_id, 0x56);
382 assert_eq!(b.t2_system_id, 0x789A);
383 assert_eq!(b.siso_miso, Some(0));
384 assert_eq!(b.bandwidth, Some(4));
385 assert_eq!(b.guard_interval, Some(6));
386 assert_eq!(b.transmission_mode, Some(3));
387 assert_eq!(b.other_frequency_flag, Some(false));
388 assert_eq!(b.tfs_flag, Some(true));
389 assert_eq!(b.cells.len(), 2);
390
391 assert_eq!(b.cells[0].cell_id, 0x1234);
392 assert!(b.cells[0].centre_frequencies.is_empty());
393 assert!(b.cells[0].subcells.is_empty());
394
395 assert_eq!(b.cells[1].cell_id, 0x678A);
396 assert_eq!(
397 b.cells[1].centre_frequencies,
398 vec![0x075BCD15, 0x05E30A78, 0x0FD22C32]
399 );
400 assert_eq!(b.cells[1].subcells.len(), 2);
401 assert_eq!(b.cells[1].subcells[0].cell_id_extension, 0x12);
402 assert_eq!(b.cells[1].subcells[0].transposer_frequency, 0x17EA6406);
403 assert_eq!(b.cells[1].subcells[1].cell_id_extension, 0xFA);
404 assert_eq!(b.cells[1].subcells[1].transposer_frequency, 0x0AA9FC59);
405 }
406 other => panic!("expected T2DeliverySystem, got {other:?}"),
407 }
408 let mut out = vec![0u8; d.serialized_len()];
409 let n = d.serialize_into(&mut out).unwrap();
410 assert_eq!(
411 out[..n],
412 bytes[..],
413 "byte-exact re-serialize for tsduck T2 reference"
414 );
415 }
416}