1use super::*;
3use alloc::vec;
4use alloc::vec::Vec;
5
6impl<'a> ExtensionBodyDef<'a> for T2DeliverySystem {
7 const TAG_EXTENSION: u8 = 0x04;
8 const NAME: &'static str = "T2_DELIVERY_SYSTEM";
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18#[non_exhaustive]
19pub enum T2SisoMiso {
20 Siso,
22 Miso,
24 Reserved(u8),
26}
27
28impl T2SisoMiso {
29 #[must_use]
30 pub fn from_u8(v: u8) -> Self {
32 match v {
33 0 => T2SisoMiso::Siso,
34 1 => T2SisoMiso::Miso,
35 other => T2SisoMiso::Reserved(other),
36 }
37 }
38
39 #[must_use]
40 pub fn to_u8(self) -> u8 {
42 match self {
43 T2SisoMiso::Siso => 0,
44 T2SisoMiso::Miso => 1,
45 T2SisoMiso::Reserved(v) => v,
46 }
47 }
48
49 #[must_use]
50 pub fn name(self) -> &'static str {
52 match self {
53 T2SisoMiso::Siso => "SISO",
54 T2SisoMiso::Miso => "MISO",
55 T2SisoMiso::Reserved(_) => "reserved",
56 }
57 }
58}
59dvb_common::impl_spec_display!(T2SisoMiso, Reserved);
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63#[cfg_attr(feature = "serde", derive(serde::Serialize))]
64#[non_exhaustive]
65pub enum T2Bandwidth {
66 Mhz8,
68 Mhz7,
70 Mhz6,
72 Mhz5,
74 Mhz10,
76 Mhz1_712,
78 Reserved(u8),
80}
81
82impl T2Bandwidth {
83 #[must_use]
84 pub fn from_u8(v: u8) -> Self {
86 match v {
87 0 => T2Bandwidth::Mhz8,
88 1 => T2Bandwidth::Mhz7,
89 2 => T2Bandwidth::Mhz6,
90 3 => T2Bandwidth::Mhz5,
91 4 => T2Bandwidth::Mhz10,
92 5 => T2Bandwidth::Mhz1_712,
93 other => T2Bandwidth::Reserved(other),
94 }
95 }
96
97 #[must_use]
98 pub fn to_u8(self) -> u8 {
100 match self {
101 T2Bandwidth::Mhz8 => 0,
102 T2Bandwidth::Mhz7 => 1,
103 T2Bandwidth::Mhz6 => 2,
104 T2Bandwidth::Mhz5 => 3,
105 T2Bandwidth::Mhz10 => 4,
106 T2Bandwidth::Mhz1_712 => 5,
107 T2Bandwidth::Reserved(v) => v,
108 }
109 }
110
111 #[must_use]
112 pub fn name(self) -> &'static str {
114 match self {
115 T2Bandwidth::Mhz8 => "8 MHz",
116 T2Bandwidth::Mhz7 => "7 MHz",
117 T2Bandwidth::Mhz6 => "6 MHz",
118 T2Bandwidth::Mhz5 => "5 MHz",
119 T2Bandwidth::Mhz10 => "10 MHz",
120 T2Bandwidth::Mhz1_712 => "1.712 MHz",
121 T2Bandwidth::Reserved(_) => "reserved",
122 }
123 }
124}
125dvb_common::impl_spec_display!(T2Bandwidth, Reserved);
126
127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129#[cfg_attr(feature = "serde", derive(serde::Serialize))]
130#[non_exhaustive]
131pub enum T2GuardInterval {
132 G1_32,
134 G1_16,
136 G1_8,
138 G1_4,
140 G1_128,
142 G19_128,
144 G19_256,
146 Reserved(u8),
148}
149
150impl T2GuardInterval {
151 #[must_use]
152 pub fn from_u8(v: u8) -> Self {
154 match v {
155 0 => T2GuardInterval::G1_32,
156 1 => T2GuardInterval::G1_16,
157 2 => T2GuardInterval::G1_8,
158 3 => T2GuardInterval::G1_4,
159 4 => T2GuardInterval::G1_128,
160 5 => T2GuardInterval::G19_128,
161 6 => T2GuardInterval::G19_256,
162 other => T2GuardInterval::Reserved(other),
163 }
164 }
165
166 #[must_use]
167 pub fn to_u8(self) -> u8 {
169 match self {
170 T2GuardInterval::G1_32 => 0,
171 T2GuardInterval::G1_16 => 1,
172 T2GuardInterval::G1_8 => 2,
173 T2GuardInterval::G1_4 => 3,
174 T2GuardInterval::G1_128 => 4,
175 T2GuardInterval::G19_128 => 5,
176 T2GuardInterval::G19_256 => 6,
177 T2GuardInterval::Reserved(v) => v,
178 }
179 }
180
181 #[must_use]
182 pub fn name(self) -> &'static str {
184 match self {
185 T2GuardInterval::G1_32 => "1/32",
186 T2GuardInterval::G1_16 => "1/16",
187 T2GuardInterval::G1_8 => "1/8",
188 T2GuardInterval::G1_4 => "1/4",
189 T2GuardInterval::G1_128 => "1/128",
190 T2GuardInterval::G19_128 => "19/128",
191 T2GuardInterval::G19_256 => "19/256",
192 T2GuardInterval::Reserved(_) => "reserved",
193 }
194 }
195}
196dvb_common::impl_spec_display!(T2GuardInterval, Reserved);
197
198#[derive(Debug, Clone, Copy, PartialEq, Eq)]
200#[cfg_attr(feature = "serde", derive(serde::Serialize))]
201#[non_exhaustive]
202pub enum T2TransmissionMode {
203 Mode2k,
205 Mode8k,
207 Mode4k,
209 Mode1k,
211 Mode16k,
213 Mode32k,
215 Reserved(u8),
217}
218
219impl T2TransmissionMode {
220 #[must_use]
221 pub fn from_u8(v: u8) -> Self {
223 match v {
224 0 => T2TransmissionMode::Mode2k,
225 1 => T2TransmissionMode::Mode8k,
226 2 => T2TransmissionMode::Mode4k,
227 3 => T2TransmissionMode::Mode1k,
228 4 => T2TransmissionMode::Mode16k,
229 5 => T2TransmissionMode::Mode32k,
230 other => T2TransmissionMode::Reserved(other),
231 }
232 }
233
234 #[must_use]
235 pub fn to_u8(self) -> u8 {
237 match self {
238 T2TransmissionMode::Mode2k => 0,
239 T2TransmissionMode::Mode8k => 1,
240 T2TransmissionMode::Mode4k => 2,
241 T2TransmissionMode::Mode1k => 3,
242 T2TransmissionMode::Mode16k => 4,
243 T2TransmissionMode::Mode32k => 5,
244 T2TransmissionMode::Reserved(v) => v,
245 }
246 }
247
248 #[must_use]
249 pub fn name(self) -> &'static str {
251 match self {
252 T2TransmissionMode::Mode2k => "2k",
253 T2TransmissionMode::Mode8k => "8k",
254 T2TransmissionMode::Mode4k => "4k",
255 T2TransmissionMode::Mode1k => "1k",
256 T2TransmissionMode::Mode16k => "16k",
257 T2TransmissionMode::Mode32k => "32k",
258 T2TransmissionMode::Reserved(_) => "reserved",
259 }
260 }
261}
262dvb_common::impl_spec_display!(T2TransmissionMode, Reserved);
263
264#[derive(Debug, Clone, PartialEq, Eq)]
270#[cfg_attr(feature = "serde", derive(serde::Serialize))]
271pub struct T2Cell {
272 pub cell_id: u16,
274 pub centre_frequencies: Vec<u32>,
277 pub subcells: Vec<T2Subcell>,
279}
280
281impl T2Cell {
282 #[must_use]
284 pub fn centre_frequencies_hz(&self) -> Vec<u64> {
285 self.centre_frequencies
286 .iter()
287 .map(|&f| u64::from(f) * 10)
288 .collect()
289 }
290}
291
292#[derive(Debug, Clone, Copy, PartialEq, Eq)]
294#[cfg_attr(feature = "serde", derive(serde::Serialize))]
295pub struct T2Subcell {
296 pub cell_id_extension: u8,
298 pub transposer_frequency: u32,
300}
301
302impl T2Subcell {
303 #[must_use]
305 pub fn transposer_frequency_hz(&self) -> u64 {
306 u64::from(self.transposer_frequency) * 10
307 }
308}
309
310#[derive(Debug, Clone, PartialEq, Eq)]
312#[cfg_attr(feature = "serde", derive(serde::Serialize))]
313pub struct T2DeliverySystem {
314 pub plp_id: u8,
316 pub t2_system_id: u16,
318 pub siso_miso: Option<T2SisoMiso>,
320 pub bandwidth: Option<T2Bandwidth>,
322 pub guard_interval: Option<T2GuardInterval>,
324 pub transmission_mode: Option<T2TransmissionMode>,
326 pub other_frequency_flag: Option<bool>,
328 pub tfs_flag: Option<bool>,
330 pub cells: Vec<T2Cell>,
332}
333
334impl<'a> Parse<'a> for T2DeliverySystem {
335 type Error = crate::error::Error;
336 fn parse(sel: &'a [u8]) -> Result<Self> {
337 if sel.len() < T2_FIXED_PREFIX_LEN {
338 return Err(Error::BufferTooShort {
339 need: T2_FIXED_PREFIX_LEN,
340 have: sel.len(),
341 what: "T2_delivery_system body",
342 });
343 }
344 let plp_id = sel[0];
345 let (t2_id_bytes, _) = sel[1..]
346 .split_first_chunk::<2>()
347 .ok_or(Error::BufferTooShort {
348 need: T2_FIXED_PREFIX_LEN,
349 have: sel.len(),
350 what: "T2_delivery_system body",
351 })?;
352 let t2_system_id = u16::from_be_bytes(*t2_id_bytes);
353 let mut pos = T2_FIXED_PREFIX_LEN;
354 let (
355 siso_miso,
356 bandwidth,
357 guard_interval,
358 transmission_mode,
359 other_frequency_flag,
360 tfs_flag,
361 ) = if sel.len() > T2_FIXED_PREFIX_LEN {
362 if sel.len() < T2_FIXED_PREFIX_LEN + T2_FLAGS_BLOCK_LEN {
363 return Err(Error::BufferTooShort {
364 need: T2_FIXED_PREFIX_LEN + T2_FLAGS_BLOCK_LEN,
365 have: sel.len(),
366 what: "T2_delivery_system body",
367 });
368 }
369 let b0 = sel[pos];
370 let b1 = sel[pos + 1];
371 pos += T2_FLAGS_BLOCK_LEN;
372 (
373 Some(T2SisoMiso::from_u8(b0 >> 6)),
374 Some(T2Bandwidth::from_u8((b0 >> 2) & 0x0F)),
375 Some(T2GuardInterval::from_u8(b1 >> 5)),
376 Some(T2TransmissionMode::from_u8((b1 >> 2) & 0x07)),
377 Some((b1 & 0x02) != 0),
378 Some((b1 & 0x01) != 0),
379 )
380 } else {
381 (None, None, None, None, None, None)
382 };
383 let cells = if siso_miso.is_some() {
384 let tfs = tfs_flag.unwrap();
385 let mut cells = Vec::new();
386 while pos < sel.len() {
387 if pos + 2 > sel.len() {
388 return Err(Error::BufferTooShort {
389 need: pos + 2,
390 have: sel.len(),
391 what: "T2_delivery_system body",
392 });
393 }
394 let (cell_id_bytes, _) = sel
395 .get(pos..)
396 .and_then(|s| s.split_first_chunk::<2>())
397 .ok_or(Error::BufferTooShort {
398 need: pos + 2,
399 have: sel.len(),
400 what: "T2_delivery_system body",
401 })?;
402 let cell_id = u16::from_be_bytes(*cell_id_bytes);
403 pos += 2;
404 let centre_frequencies = if tfs {
405 if pos >= sel.len() {
406 return Err(Error::BufferTooShort {
407 need: pos + 1,
408 have: sel.len(),
409 what: "T2_delivery_system body",
410 });
411 }
412 let freq_loop_len = sel[pos] as usize;
413 pos += 1;
414 if freq_loop_len % 4 != 0 {
415 return Err(invalid(
416 "T2_delivery_system: frequency_loop_length not a multiple of 4",
417 ));
418 }
419 if pos + freq_loop_len > sel.len() {
420 return Err(Error::BufferTooShort {
421 need: pos + freq_loop_len,
422 have: sel.len(),
423 what: "T2_delivery_system body",
424 });
425 }
426 let end = pos + freq_loop_len;
427 let mut freqs = Vec::with_capacity(freq_loop_len / 4);
428 while pos < end {
429 let (fb, _) = sel
430 .get(pos..)
431 .and_then(|s| s.split_first_chunk::<4>())
432 .ok_or(Error::BufferTooShort {
433 need: pos + 4,
434 have: sel.len(),
435 what: "T2_delivery_system body",
436 })?;
437 freqs.push(u32::from_be_bytes(*fb));
438 pos += 4;
439 }
440 freqs
441 } else {
442 if pos + 4 > sel.len() {
443 return Err(Error::BufferTooShort {
444 need: pos + 4,
445 have: sel.len(),
446 what: "T2_delivery_system body",
447 });
448 }
449 let (freq_bytes, _) = sel
450 .get(pos..)
451 .and_then(|s| s.split_first_chunk::<4>())
452 .ok_or(Error::BufferTooShort {
453 need: pos + 4,
454 have: sel.len(),
455 what: "T2_delivery_system body",
456 })?;
457 let freq = u32::from_be_bytes(*freq_bytes);
458 pos += 4;
459 vec![freq]
460 };
461 if pos >= sel.len() {
462 return Err(Error::BufferTooShort {
463 need: pos + 1,
464 have: sel.len(),
465 what: "T2_delivery_system body",
466 });
467 }
468 let subcell_loop_len = sel[pos] as usize;
469 pos += 1;
470 if subcell_loop_len % 5 != 0 {
471 return Err(invalid(
472 "T2_delivery_system: subcell_info_loop_length not a multiple of 5",
473 ));
474 }
475 if pos + subcell_loop_len > sel.len() {
476 return Err(Error::BufferTooShort {
477 need: pos + subcell_loop_len,
478 have: sel.len(),
479 what: "T2_delivery_system body",
480 });
481 }
482 let end = pos + subcell_loop_len;
483 let mut subcells = Vec::with_capacity(subcell_loop_len / 5);
484 while pos < end {
485 let (tf_bytes, _) = sel
486 .get(pos + 1..)
487 .and_then(|s| s.split_first_chunk::<4>())
488 .ok_or(Error::BufferTooShort {
489 need: pos + 5,
490 have: sel.len(),
491 what: "T2_delivery_system body",
492 })?;
493 subcells.push(T2Subcell {
494 cell_id_extension: sel[pos],
495 transposer_frequency: u32::from_be_bytes(*tf_bytes),
496 });
497 pos += 5;
498 }
499 cells.push(T2Cell {
500 cell_id,
501 centre_frequencies,
502 subcells,
503 });
504 }
505 cells
506 } else {
507 Vec::new()
508 };
509 Ok(T2DeliverySystem {
510 plp_id,
511 t2_system_id,
512 siso_miso,
513 bandwidth,
514 guard_interval,
515 transmission_mode,
516 other_frequency_flag,
517 tfs_flag,
518 cells,
519 })
520 }
521}
522
523impl Serialize for T2DeliverySystem {
524 type Error = crate::error::Error;
525 fn serialized_len(&self) -> usize {
526 let mut len = T2_FIXED_PREFIX_LEN;
527 if self.siso_miso.is_some() {
528 len += T2_FLAGS_BLOCK_LEN;
529 let tfs = self.tfs_flag.unwrap_or(false);
530 for cell in &self.cells {
531 len += 2; if tfs {
533 len += 1 + cell.centre_frequencies.len() * 4;
534 } else {
535 len += 4;
536 }
537 len += 1 + cell.subcells.len() * 5;
538 }
539 }
540 len
541 }
542 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
543 let len = self.serialized_len();
544 if buf.len() < len {
545 return Err(Error::OutputBufferTooSmall {
546 need: len,
547 have: buf.len(),
548 });
549 }
550 buf[0] = self.plp_id;
551 buf[1..3].copy_from_slice(&self.t2_system_id.to_be_bytes());
552 let mut p = T2_FIXED_PREFIX_LEN;
553 if let (Some(sm), Some(bw), Some(gi), Some(tm), Some(off), Some(tfs)) = (
554 self.siso_miso,
555 self.bandwidth,
556 self.guard_interval,
557 self.transmission_mode,
558 self.other_frequency_flag,
559 self.tfs_flag,
560 ) {
561 buf[p] = (sm.to_u8() << 6) | ((bw.to_u8() & 0x0F) << 2) | 0x03;
562 buf[p + 1] = (gi.to_u8() << 5)
563 | ((tm.to_u8() & 0x07) << 2)
564 | (u8::from(off) << 1)
565 | u8::from(tfs);
566 p += T2_FLAGS_BLOCK_LEN;
567 for cell in &self.cells {
568 buf[p..p + 2].copy_from_slice(&cell.cell_id.to_be_bytes());
569 p += 2;
570 if tfs {
571 let freq_len = (cell.centre_frequencies.len() * 4) as u8;
572 buf[p] = freq_len;
573 p += 1;
574 for &freq in &cell.centre_frequencies {
575 buf[p..p + 4].copy_from_slice(&freq.to_be_bytes());
576 p += 4;
577 }
578 } else {
579 let freq = cell.centre_frequencies.first().copied().unwrap_or(0);
580 buf[p..p + 4].copy_from_slice(&freq.to_be_bytes());
581 p += 4;
582 }
583 let subcell_len = (cell.subcells.len() * 5) as u8;
584 buf[p] = subcell_len;
585 p += 1;
586 for sc in &cell.subcells {
587 buf[p] = sc.cell_id_extension;
588 buf[p + 1..p + 5].copy_from_slice(&sc.transposer_frequency.to_be_bytes());
589 p += 5;
590 }
591 }
592 }
593 Ok(len)
594 }
595}
596
597#[cfg(test)]
598mod tests {
599 use super::*;
600 use crate::descriptors::extension::test_support::*;
601 use crate::descriptors::extension::{ExtensionBody, ExtensionDescriptor};
602
603 #[test]
604 fn t2_bandwidth_roundtrip() {
605 for b in 0..=0xFFu8 {
606 assert_eq!(T2Bandwidth::from_u8(b).to_u8(), b);
607 }
608 }
609
610 #[test]
611 fn t2_guard_interval_roundtrip() {
612 for b in 0..=0xFFu8 {
613 assert_eq!(T2GuardInterval::from_u8(b).to_u8(), b);
614 }
615 }
616
617 #[test]
618 fn t2_transmission_mode_roundtrip() {
619 for b in 0..=0xFFu8 {
620 assert_eq!(T2TransmissionMode::from_u8(b).to_u8(), b);
621 }
622 }
623
624 #[test]
625 fn parse_t2_minimal() {
626 let sel = [0x07, 0x12, 0x34];
628 let bytes = wrap(0x04, &sel);
629 let d = ExtensionDescriptor::parse(&bytes).unwrap();
630 match &d.body {
631 ExtensionBody::T2DeliverySystem(b) => {
632 assert_eq!(b.plp_id, 0x07);
633 assert_eq!(b.t2_system_id, 0x1234);
634 assert_eq!(b.siso_miso, None);
635 assert!(b.cells.is_empty());
636 }
637 other => panic!("expected T2DeliverySystem, got {other:?}"),
638 }
639 round_trip(&d);
640 }
641
642 #[test]
643 fn parse_t2_structured_flags_and_cells() {
644 let b0: u8 = ((0x04 & 0x0F) << 2) | 0x03; let b1: u8 = (0x06 << 5) | ((0x03 & 0x07) << 2) | (u8::from(false) << 1) | u8::from(true);
648 let cell1 = [0x12, 0x34, 0x00, 0x00];
650 let f1 = 0x01020304u32;
652 let f2 = 0x05060708u32;
653 let f3 = 0x090A0B0Cu32;
654 let sc1_id = 0x10u8;
655 let sc1_freq = 0x11121314u32;
656 let sc2_id = 0x20u8;
657 let sc2_freq = 0x21222324u32;
658 let mut cell2 = Vec::new();
659 cell2.extend_from_slice(&0x5678u16.to_be_bytes());
660 cell2.push(12);
661 cell2.extend_from_slice(&f1.to_be_bytes());
662 cell2.extend_from_slice(&f2.to_be_bytes());
663 cell2.extend_from_slice(&f3.to_be_bytes());
664 cell2.push(10);
665 cell2.push(sc1_id);
666 cell2.extend_from_slice(&sc1_freq.to_be_bytes());
667 cell2.push(sc2_id);
668 cell2.extend_from_slice(&sc2_freq.to_be_bytes());
669 let mut sel = vec![0x07, 0x12, 0x34, b0, b1];
670 sel.extend_from_slice(&cell1);
671 sel.extend_from_slice(&cell2);
672 let bytes = wrap(0x04, &sel);
673 let d = ExtensionDescriptor::parse(&bytes).unwrap();
674 match &d.body {
675 ExtensionBody::T2DeliverySystem(b) => {
676 assert_eq!(b.plp_id, 0x07);
677 assert_eq!(b.t2_system_id, 0x1234);
678 assert_eq!(b.siso_miso, Some(T2SisoMiso::Siso));
679 assert_eq!(b.bandwidth, Some(T2Bandwidth::Mhz10));
680 assert_eq!(b.guard_interval, Some(T2GuardInterval::G19_256));
681 assert_eq!(b.transmission_mode, Some(T2TransmissionMode::Mode1k));
682 assert_eq!(b.other_frequency_flag, Some(false));
683 assert_eq!(b.tfs_flag, Some(true));
684 assert_eq!(b.cells.len(), 2);
685 assert_eq!(b.cells[0].cell_id, 0x1234);
687 assert!(b.cells[0].centre_frequencies.is_empty());
688 assert!(b.cells[0].subcells.is_empty());
689 assert_eq!(b.cells[1].cell_id, 0x5678);
691 assert_eq!(b.cells[1].centre_frequencies, vec![f1, f2, f3]);
692 assert_eq!(b.cells[1].subcells.len(), 2);
693 assert_eq!(b.cells[1].subcells[0].cell_id_extension, sc1_id);
694 assert_eq!(b.cells[1].subcells[0].transposer_frequency, sc1_freq);
695 assert_eq!(b.cells[1].subcells[1].cell_id_extension, sc2_id);
696 assert_eq!(b.cells[1].subcells[1].transposer_frequency, sc2_freq);
697
698 assert_eq!(
700 b.cells[1].subcells[0].transposer_frequency_hz(),
701 u64::from(sc1_freq) * 10
702 );
703 assert_eq!(
704 b.cells[1].centre_frequencies_hz(),
705 vec![u64::from(f1) * 10, u64::from(f2) * 10, u64::from(f3) * 10]
706 );
707 }
708 other => panic!("expected T2DeliverySystem, got {other:?}"),
709 }
710 round_trip(&d);
711 }
712
713 #[test]
714 fn tsduck_t2_reference() {
715 let bytes = from_hex(
716 "7f240456789a13cd12340000678a0c075bcd1505e30a780fd22c320a1217ea6406fa0aa9fc59",
717 );
718 let d = ExtensionDescriptor::parse(&bytes).unwrap();
719 match &d.body {
720 ExtensionBody::T2DeliverySystem(b) => {
721 assert_eq!(b.plp_id, 0x56);
722 assert_eq!(b.t2_system_id, 0x789A);
723 assert_eq!(b.siso_miso, Some(T2SisoMiso::Siso));
724 assert_eq!(b.bandwidth, Some(T2Bandwidth::Mhz10));
725 assert_eq!(b.guard_interval, Some(T2GuardInterval::G19_256));
726 assert_eq!(b.transmission_mode, Some(T2TransmissionMode::Mode1k));
727 assert_eq!(b.other_frequency_flag, Some(false));
728 assert_eq!(b.tfs_flag, Some(true));
729 assert_eq!(b.cells.len(), 2);
730
731 assert_eq!(b.cells[0].cell_id, 0x1234);
732 assert!(b.cells[0].centre_frequencies.is_empty());
733 assert!(b.cells[0].subcells.is_empty());
734
735 assert_eq!(b.cells[1].cell_id, 0x678A);
736 assert_eq!(
737 b.cells[1].centre_frequencies,
738 vec![0x075BCD15, 0x05E30A78, 0x0FD22C32]
739 );
740 assert_eq!(b.cells[1].subcells.len(), 2);
741 assert_eq!(b.cells[1].subcells[0].cell_id_extension, 0x12);
742 assert_eq!(b.cells[1].subcells[0].transposer_frequency, 0x17EA6406);
743 assert_eq!(b.cells[1].subcells[1].cell_id_extension, 0xFA);
744 assert_eq!(b.cells[1].subcells[1].transposer_frequency, 0x0AA9FC59);
745 }
746 other => panic!("expected T2DeliverySystem, got {other:?}"),
747 }
748 let mut out = vec![0u8; d.serialized_len()];
749 let n = d.serialize_into(&mut out).unwrap();
750 assert_eq!(
751 out[..n],
752 bytes[..],
753 "byte-exact re-serialize for tsduck T2 reference"
754 );
755 }
756}