1use alloc::vec;
15use alloc::vec::Vec;
16use broadcast_common::bits::{BitReader, BitWriter};
17
18use super::enums::{
19 AuxStreamType, PlpCodeRate, PlpFecType, PlpMode, PlpModulation, PlpPayloadType, PlpType,
20};
21
22const SUB_SLICES_PER_FRAME_BITS: u32 = 15;
25const NUM_PLP_BITS: u32 = 8;
26const NUM_AUX_BITS: u32 = 4;
27const AUX_CONFIG_RFU_BITS: u32 = 8;
28const RF_IDX_BITS: u32 = 3;
30const FREQUENCY_BITS: u32 = 32;
31const FEF_TYPE_BITS: u32 = 4;
33const FEF_LENGTH_BITS: u32 = 22;
34const FEF_INTERVAL_BITS: u32 = 8;
35const PLP_ID_BITS: u32 = 8;
37const PLP_TYPE_BITS: u32 = 3;
38const PLP_PAYLOAD_TYPE_BITS: u32 = 5;
39const FF_FLAG_BITS: u32 = 1;
40const FIRST_RF_IDX_BITS: u32 = 3;
41const FIRST_FRAME_IDX_BITS: u32 = 8;
42const PLP_GROUP_ID_BITS: u32 = 8;
43const PLP_COD_BITS: u32 = 3;
44const PLP_MOD_BITS: u32 = 3;
45const PLP_ROTATION_BITS: u32 = 1;
46const PLP_FEC_TYPE_BITS: u32 = 2;
47const PLP_NUM_BLOCKS_MAX_BITS: u32 = 10;
48const FRAME_INTERVAL_BITS: u32 = 8;
49const TIME_IL_LENGTH_BITS: u32 = 8;
50const TIME_IL_TYPE_BITS: u32 = 1;
51const IN_BAND_A_FLAG_BITS: u32 = 1;
52const IN_BAND_B_FLAG_BITS: u32 = 1;
53const PLP_RESERVED_1_BITS: u32 = 11;
54const PLP_MODE_BITS: u32 = 2;
55const STATIC_FLAG_BITS: u32 = 1;
56const STATIC_PADDING_FLAG_BITS: u32 = 1;
57const FEF_LENGTH_MSB_BITS: u32 = 2;
59const CONF_RESERVED_2_BITS: u32 = 30;
60const AUX_STREAM_TYPE_BITS: u32 = 4;
62const AUX_PRIVATE_CONF_BITS: u32 = 28;
63
64const FRAME_IDX_BITS: u32 = 8;
67const SUB_SLICE_INTERVAL_BITS: u32 = 22;
68const TYPE_2_START_BITS: u32 = 22;
69const L1_CHANGE_COUNTER_BITS: u32 = 8;
70const START_RF_IDX_BITS: u32 = 3;
71const DYN_RESERVED_1_BITS: u32 = 8;
72const DYN_PLP_ID_BITS: u32 = 8;
74const PLP_START_BITS: u32 = 22;
75const PLP_NUM_BLOCKS_BITS: u32 = 10;
76const DYN_PLP_RESERVED_2_BITS: u32 = 8;
77const DYN_RESERVED_3_BITS: u32 = 8;
79const AUX_PRIVATE_DYN_BITS: u32 = 48;
81
82#[derive(Debug, Clone, PartialEq, Eq)]
86#[cfg_attr(feature = "serde", derive(serde::Serialize))]
87#[non_exhaustive]
88pub struct RfFrequency {
89 pub rf_idx: u8,
91 pub frequency: u32,
93}
94
95impl RfFrequency {
96 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
97 let rf_idx = r.read_bits(RF_IDX_BITS)? as u8;
98 let frequency = r.read_bits(FREQUENCY_BITS)? as u32;
99 Ok(Self { rf_idx, frequency })
100 }
101
102 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
103 w.write_bits(u64::from(self.rf_idx), RF_IDX_BITS)?;
104 w.write_bits(u64::from(self.frequency), FREQUENCY_BITS)?;
105 Ok(())
106 }
107
108 const fn bits() -> usize {
109 (RF_IDX_BITS + FREQUENCY_BITS) as usize
110 }
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
119#[cfg_attr(feature = "serde", derive(serde::Serialize))]
120#[non_exhaustive]
121pub struct FefInfo {
122 pub fef_type: u8,
124 pub fef_length: u32,
126 pub fef_interval: u8,
128}
129
130impl FefInfo {
131 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
132 let fef_type = r.read_bits(FEF_TYPE_BITS)? as u8;
133 let fef_length = r.read_bits(FEF_LENGTH_BITS)? as u32;
134 let fef_interval = r.read_bits(FEF_INTERVAL_BITS)? as u8;
135 Ok(Self {
136 fef_type,
137 fef_length,
138 fef_interval,
139 })
140 }
141
142 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
143 w.write_bits(u64::from(self.fef_type), FEF_TYPE_BITS)?;
144 w.write_bits(u64::from(self.fef_length), FEF_LENGTH_BITS)?;
145 w.write_bits(u64::from(self.fef_interval), FEF_INTERVAL_BITS)?;
146 Ok(())
147 }
148
149 const fn bits() -> usize {
150 (FEF_TYPE_BITS + FEF_LENGTH_BITS + FEF_INTERVAL_BITS) as usize
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq)]
158#[cfg_attr(feature = "serde", derive(serde::Serialize))]
159#[non_exhaustive]
160pub struct PlpConfig {
161 pub plp_id: u8,
163 pub plp_type: PlpType,
165 pub plp_payload_type: PlpPayloadType,
167 pub ff_flag: bool,
169 pub first_rf_idx: u8,
171 pub first_frame_idx: u8,
173 pub plp_group_id: u8,
175 pub plp_cod: u8,
177 pub plp_mod: PlpModulation,
179 pub plp_rotation: bool,
181 pub plp_fec_type: PlpFecType,
183 pub plp_num_blocks_max: u16,
185 pub frame_interval: u8,
187 pub time_il_length: u8,
189 pub time_il_type: bool,
191 pub in_band_a_flag: bool,
193 pub in_band_b_flag: bool,
195 pub reserved_1: u16,
197 pub plp_mode: PlpMode,
199 pub static_flag: bool,
201 pub static_padding_flag: bool,
203}
204
205impl PlpConfig {
206 #[must_use]
212 pub fn code_rate(&self) -> PlpCodeRate {
213 PlpCodeRate::from_u8(self.plp_cod)
214 }
215
216 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
217 let plp_id = r.read_bits(PLP_ID_BITS)? as u8;
218 let plp_type = PlpType::from_u8(r.read_bits(PLP_TYPE_BITS)? as u8);
219 let plp_payload_type = PlpPayloadType::from_u8(r.read_bits(PLP_PAYLOAD_TYPE_BITS)? as u8);
220 let ff_flag = r.read_bool()?;
221 let first_rf_idx = r.read_bits(FIRST_RF_IDX_BITS)? as u8;
222 let first_frame_idx = r.read_bits(FIRST_FRAME_IDX_BITS)? as u8;
223 let plp_group_id = r.read_bits(PLP_GROUP_ID_BITS)? as u8;
224 let plp_cod = r.read_bits(PLP_COD_BITS)? as u8;
225 let plp_mod = PlpModulation::from_u8(r.read_bits(PLP_MOD_BITS)? as u8);
226 let plp_rotation = r.read_bool()?;
227 let plp_fec_type = PlpFecType::from_u8(r.read_bits(PLP_FEC_TYPE_BITS)? as u8);
228 let plp_num_blocks_max = r.read_bits(PLP_NUM_BLOCKS_MAX_BITS)? as u16;
229 let frame_interval = r.read_bits(FRAME_INTERVAL_BITS)? as u8;
230 let time_il_length = r.read_bits(TIME_IL_LENGTH_BITS)? as u8;
231 let time_il_type = r.read_bool()?;
232 let in_band_a_flag = r.read_bool()?;
233 let in_band_b_flag = r.read_bool()?;
234 let reserved_1 = r.read_bits(PLP_RESERVED_1_BITS)? as u16;
235 let plp_mode = PlpMode::from_u8(r.read_bits(PLP_MODE_BITS)? as u8);
236 let static_flag = r.read_bool()?;
237 let static_padding_flag = r.read_bool()?;
238 Ok(Self {
239 plp_id,
240 plp_type,
241 plp_payload_type,
242 ff_flag,
243 first_rf_idx,
244 first_frame_idx,
245 plp_group_id,
246 plp_cod,
247 plp_mod,
248 plp_rotation,
249 plp_fec_type,
250 plp_num_blocks_max,
251 frame_interval,
252 time_il_length,
253 time_il_type,
254 in_band_a_flag,
255 in_band_b_flag,
256 reserved_1,
257 plp_mode,
258 static_flag,
259 static_padding_flag,
260 })
261 }
262
263 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
264 w.write_bits(u64::from(self.plp_id), PLP_ID_BITS)?;
265 w.write_bits(u64::from(self.plp_type.to_u8()), PLP_TYPE_BITS)?;
266 w.write_bits(
267 u64::from(self.plp_payload_type.to_u8()),
268 PLP_PAYLOAD_TYPE_BITS,
269 )?;
270 w.write_bool(self.ff_flag)?;
271 w.write_bits(u64::from(self.first_rf_idx), FIRST_RF_IDX_BITS)?;
272 w.write_bits(u64::from(self.first_frame_idx), FIRST_FRAME_IDX_BITS)?;
273 w.write_bits(u64::from(self.plp_group_id), PLP_GROUP_ID_BITS)?;
274 w.write_bits(u64::from(self.plp_cod), PLP_COD_BITS)?;
275 w.write_bits(u64::from(self.plp_mod.to_u8()), PLP_MOD_BITS)?;
276 w.write_bool(self.plp_rotation)?;
277 w.write_bits(u64::from(self.plp_fec_type.to_u8()), PLP_FEC_TYPE_BITS)?;
278 w.write_bits(u64::from(self.plp_num_blocks_max), PLP_NUM_BLOCKS_MAX_BITS)?;
279 w.write_bits(u64::from(self.frame_interval), FRAME_INTERVAL_BITS)?;
280 w.write_bits(u64::from(self.time_il_length), TIME_IL_LENGTH_BITS)?;
281 w.write_bool(self.time_il_type)?;
282 w.write_bool(self.in_band_a_flag)?;
283 w.write_bool(self.in_band_b_flag)?;
284 w.write_bits(u64::from(self.reserved_1), PLP_RESERVED_1_BITS)?;
285 w.write_bits(u64::from(self.plp_mode.to_u8()), PLP_MODE_BITS)?;
286 w.write_bool(self.static_flag)?;
287 w.write_bool(self.static_padding_flag)?;
288 Ok(())
289 }
290
291 const fn bits() -> usize {
292 (PLP_ID_BITS
293 + PLP_TYPE_BITS
294 + PLP_PAYLOAD_TYPE_BITS
295 + FF_FLAG_BITS
296 + FIRST_RF_IDX_BITS
297 + FIRST_FRAME_IDX_BITS
298 + PLP_GROUP_ID_BITS
299 + PLP_COD_BITS
300 + PLP_MOD_BITS
301 + PLP_ROTATION_BITS
302 + PLP_FEC_TYPE_BITS
303 + PLP_NUM_BLOCKS_MAX_BITS
304 + FRAME_INTERVAL_BITS
305 + TIME_IL_LENGTH_BITS
306 + TIME_IL_TYPE_BITS
307 + IN_BAND_A_FLAG_BITS
308 + IN_BAND_B_FLAG_BITS
309 + PLP_RESERVED_1_BITS
310 + PLP_MODE_BITS
311 + STATIC_FLAG_BITS
312 + STATIC_PADDING_FLAG_BITS) as usize
313 }
314}
315
316#[derive(Debug, Clone, PartialEq, Eq)]
320#[cfg_attr(feature = "serde", derive(serde::Serialize))]
321#[non_exhaustive]
322pub struct AuxConfig {
323 pub aux_stream_type: AuxStreamType,
325 pub aux_private_conf: u32,
327}
328
329impl AuxConfig {
330 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
331 let aux_stream_type = AuxStreamType::from_u8(r.read_bits(AUX_STREAM_TYPE_BITS)? as u8);
332 let aux_private_conf = r.read_bits(AUX_PRIVATE_CONF_BITS)? as u32;
333 Ok(Self {
334 aux_stream_type,
335 aux_private_conf,
336 })
337 }
338
339 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
340 w.write_bits(
341 u64::from(self.aux_stream_type.to_u8()),
342 AUX_STREAM_TYPE_BITS,
343 )?;
344 w.write_bits(u64::from(self.aux_private_conf), AUX_PRIVATE_CONF_BITS)?;
345 Ok(())
346 }
347
348 const fn bits() -> usize {
349 (AUX_STREAM_TYPE_BITS + AUX_PRIVATE_CONF_BITS) as usize
350 }
351}
352
353#[derive(Debug, Clone, PartialEq, Eq)]
360#[cfg_attr(feature = "serde", derive(serde::Serialize))]
361#[non_exhaustive]
362pub struct L1PostConfigurable {
363 pub sub_slices_per_frame: u16,
365 pub num_plp: u8,
367 pub num_aux: u8,
369 pub aux_config_rfu: u8,
371 pub rf: Vec<RfFrequency>,
373 pub fef: Option<FefInfo>,
375 pub plps: Vec<PlpConfig>,
377 pub fef_length_msb: u8,
379 pub reserved_2: u32,
381 pub aux: Vec<AuxConfig>,
383}
384
385impl L1PostConfigurable {
386 pub fn parse(bytes: &[u8], num_rf: u8, fef_present: bool) -> crate::error::Result<Self> {
391 let mut r = BitReader::new(bytes);
392
393 let sub_slices_per_frame = r.read_bits(SUB_SLICES_PER_FRAME_BITS)? as u16;
394 let num_plp = r.read_bits(NUM_PLP_BITS)? as u8;
395 let num_aux = r.read_bits(NUM_AUX_BITS)? as u8;
396 let aux_config_rfu = r.read_bits(AUX_CONFIG_RFU_BITS)? as u8;
397
398 let mut rf = Vec::with_capacity(num_rf as usize);
399 for _ in 0..num_rf {
400 rf.push(RfFrequency::parse(&mut r)?);
401 }
402
403 let fef = if fef_present {
404 Some(FefInfo::parse(&mut r)?)
405 } else {
406 None
407 };
408
409 let mut plps = Vec::with_capacity(num_plp as usize);
410 for _ in 0..num_plp {
411 plps.push(PlpConfig::parse(&mut r)?);
412 }
413
414 let fef_length_msb = r.read_bits(FEF_LENGTH_MSB_BITS)? as u8;
415 let reserved_2 = r.read_bits(CONF_RESERVED_2_BITS)? as u32;
416
417 let mut aux = Vec::with_capacity(num_aux as usize);
418 for _ in 0..num_aux {
419 aux.push(AuxConfig::parse(&mut r)?);
420 }
421
422 Ok(Self {
423 sub_slices_per_frame,
424 num_plp,
425 num_aux,
426 aux_config_rfu,
427 rf,
428 fef,
429 plps,
430 fef_length_msb,
431 reserved_2,
432 aux,
433 })
434 }
435
436 #[must_use]
438 pub fn len_bits(&self) -> usize {
439 let header = (SUB_SLICES_PER_FRAME_BITS + NUM_PLP_BITS + NUM_AUX_BITS + AUX_CONFIG_RFU_BITS)
440 as usize;
441 let rf_bits = self.rf.len() * RfFrequency::bits();
442 let fef_bits = if self.fef.is_some() {
443 FefInfo::bits()
444 } else {
445 0
446 };
447 let plp_bits = self.plps.len() * PlpConfig::bits();
448 let post_loop = (FEF_LENGTH_MSB_BITS + CONF_RESERVED_2_BITS) as usize;
449 let aux_bits = self.aux.len() * AuxConfig::bits();
450 header + rf_bits + fef_bits + plp_bits + post_loop + aux_bits
451 }
452
453 pub fn serialize_bits(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
458 w.write_bits(
459 u64::from(self.sub_slices_per_frame),
460 SUB_SLICES_PER_FRAME_BITS,
461 )?;
462 w.write_bits(u64::from(self.num_plp), NUM_PLP_BITS)?;
463 w.write_bits(u64::from(self.num_aux), NUM_AUX_BITS)?;
464 w.write_bits(u64::from(self.aux_config_rfu), AUX_CONFIG_RFU_BITS)?;
465 for rf in &self.rf {
466 rf.write(w)?;
467 }
468 if let Some(fef) = &self.fef {
469 fef.write(w)?;
470 }
471 for plp in &self.plps {
472 plp.write(w)?;
473 }
474 w.write_bits(u64::from(self.fef_length_msb), FEF_LENGTH_MSB_BITS)?;
475 w.write_bits(u64::from(self.reserved_2), CONF_RESERVED_2_BITS)?;
476 for aux in &self.aux {
477 aux.write(w)?;
478 }
479 Ok(())
480 }
481}
482
483#[derive(Debug, Clone, PartialEq, Eq)]
487#[cfg_attr(feature = "serde", derive(serde::Serialize))]
488#[non_exhaustive]
489pub struct PlpDynamic {
490 pub plp_id: u8,
492 pub plp_start: u32,
494 pub plp_num_blocks: u16,
496 pub reserved_2: u8,
498}
499
500impl PlpDynamic {
501 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
502 let plp_id = r.read_bits(DYN_PLP_ID_BITS)? as u8;
503 let plp_start = r.read_bits(PLP_START_BITS)? as u32;
504 let plp_num_blocks = r.read_bits(PLP_NUM_BLOCKS_BITS)? as u16;
505 let reserved_2 = r.read_bits(DYN_PLP_RESERVED_2_BITS)? as u8;
506 Ok(Self {
507 plp_id,
508 plp_start,
509 plp_num_blocks,
510 reserved_2,
511 })
512 }
513
514 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
515 w.write_bits(u64::from(self.plp_id), DYN_PLP_ID_BITS)?;
516 w.write_bits(u64::from(self.plp_start), PLP_START_BITS)?;
517 w.write_bits(u64::from(self.plp_num_blocks), PLP_NUM_BLOCKS_BITS)?;
518 w.write_bits(u64::from(self.reserved_2), DYN_PLP_RESERVED_2_BITS)?;
519 Ok(())
520 }
521
522 const fn bits() -> usize {
523 (DYN_PLP_ID_BITS + PLP_START_BITS + PLP_NUM_BLOCKS_BITS + DYN_PLP_RESERVED_2_BITS) as usize
524 }
525}
526
527#[derive(Debug, Clone, PartialEq, Eq)]
531#[cfg_attr(feature = "serde", derive(serde::Serialize))]
532#[non_exhaustive]
533pub struct AuxDynamic {
534 pub aux_private_dyn: u64,
536}
537
538impl AuxDynamic {
539 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
540 let aux_private_dyn = r.read_bits(AUX_PRIVATE_DYN_BITS)?;
541 Ok(Self { aux_private_dyn })
542 }
543
544 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
545 w.write_bits(self.aux_private_dyn, AUX_PRIVATE_DYN_BITS)?;
546 Ok(())
547 }
548
549 const fn bits() -> usize {
550 AUX_PRIVATE_DYN_BITS as usize
551 }
552}
553
554#[derive(Debug, Clone, PartialEq, Eq)]
562#[cfg_attr(feature = "serde", derive(serde::Serialize))]
563#[non_exhaustive]
564pub struct L1PostDynamic {
565 pub frame_idx: u8,
567 pub sub_slice_interval: u32,
569 pub type_2_start: u32,
571 pub l1_change_counter: u8,
573 pub start_rf_idx: u8,
575 pub reserved_1: u8,
577 pub plps: Vec<PlpDynamic>,
579 pub reserved_3: u8,
581 pub aux: Vec<AuxDynamic>,
583}
584
585impl L1PostDynamic {
586 pub fn parse(bytes: &[u8], num_plp: u8, num_aux: u8) -> crate::error::Result<Self> {
592 let mut r = BitReader::new(bytes);
593
594 let frame_idx = r.read_bits(FRAME_IDX_BITS)? as u8;
595 let sub_slice_interval = r.read_bits(SUB_SLICE_INTERVAL_BITS)? as u32;
596 let type_2_start = r.read_bits(TYPE_2_START_BITS)? as u32;
597 let l1_change_counter = r.read_bits(L1_CHANGE_COUNTER_BITS)? as u8;
598 let start_rf_idx = r.read_bits(START_RF_IDX_BITS)? as u8;
599 let reserved_1 = r.read_bits(DYN_RESERVED_1_BITS)? as u8;
600
601 let mut plps = Vec::with_capacity(num_plp as usize);
602 for _ in 0..num_plp {
603 plps.push(PlpDynamic::parse(&mut r)?);
604 }
605
606 let reserved_3 = r.read_bits(DYN_RESERVED_3_BITS)? as u8;
607
608 let mut aux = Vec::with_capacity(num_aux as usize);
609 for _ in 0..num_aux {
610 aux.push(AuxDynamic::parse(&mut r)?);
611 }
612
613 Ok(Self {
614 frame_idx,
615 sub_slice_interval,
616 type_2_start,
617 l1_change_counter,
618 start_rf_idx,
619 reserved_1,
620 plps,
621 reserved_3,
622 aux,
623 })
624 }
625
626 #[must_use]
628 pub fn len_bits(&self) -> usize {
629 let header = (FRAME_IDX_BITS
630 + SUB_SLICE_INTERVAL_BITS
631 + TYPE_2_START_BITS
632 + L1_CHANGE_COUNTER_BITS
633 + START_RF_IDX_BITS
634 + DYN_RESERVED_1_BITS) as usize;
635 let plp_bits = self.plps.len() * PlpDynamic::bits();
636 let post = DYN_RESERVED_3_BITS as usize;
637 let aux_bits = self.aux.len() * AuxDynamic::bits();
638 header + plp_bits + post + aux_bits
639 }
640
641 pub fn serialize_bits(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
646 w.write_bits(u64::from(self.frame_idx), FRAME_IDX_BITS)?;
647 w.write_bits(u64::from(self.sub_slice_interval), SUB_SLICE_INTERVAL_BITS)?;
648 w.write_bits(u64::from(self.type_2_start), TYPE_2_START_BITS)?;
649 w.write_bits(u64::from(self.l1_change_counter), L1_CHANGE_COUNTER_BITS)?;
650 w.write_bits(u64::from(self.start_rf_idx), START_RF_IDX_BITS)?;
651 w.write_bits(u64::from(self.reserved_1), DYN_RESERVED_1_BITS)?;
652 for plp in &self.plps {
653 plp.write(w)?;
654 }
655 w.write_bits(u64::from(self.reserved_3), DYN_RESERVED_3_BITS)?;
656 for aux in &self.aux {
657 aux.write(w)?;
658 }
659 Ok(())
660 }
661}
662
663const L1_EXT_BLOCK_TYPE_BITS: u32 = 8;
666const L1_EXT_DATA_LEN_BITS: u32 = 16;
667
668#[derive(Debug, Clone, PartialEq, Eq)]
675#[cfg_attr(feature = "serde", derive(serde::Serialize))]
676#[non_exhaustive]
677pub struct L1ExtBlock {
678 pub block_type: u8,
680 pub data_bit_len: u16,
682 pub data: Vec<u8>,
684}
685
686impl L1ExtBlock {
687 fn bits(&self) -> usize {
689 (L1_EXT_BLOCK_TYPE_BITS + L1_EXT_DATA_LEN_BITS) as usize + self.data_bit_len as usize
690 }
691
692 fn parse(r: &mut BitReader<'_>) -> crate::error::Result<Self> {
693 let block_type = r.read_bits(L1_EXT_BLOCK_TYPE_BITS)? as u8;
694 let data_bit_len = r.read_bits(L1_EXT_DATA_LEN_BITS)? as u16;
695 let n = data_bit_len as usize;
696 let mut data = vec![0u8; n.div_ceil(8)];
697 let mut done = 0usize;
698 for byte in data.iter_mut() {
699 let take = (n - done).min(8) as u32;
700 let v = r.read_bits(take)? as u8;
701 *byte = if take < 8 { v << (8 - take) } else { v };
703 done += take as usize;
704 }
705 Ok(Self {
706 block_type,
707 data_bit_len,
708 data,
709 })
710 }
711
712 fn write(&self, w: &mut BitWriter<'_>) -> crate::error::Result<()> {
713 w.write_bits(u64::from(self.block_type), L1_EXT_BLOCK_TYPE_BITS)?;
714 w.write_bits(u64::from(self.data_bit_len), L1_EXT_DATA_LEN_BITS)?;
715 let n = self.data_bit_len as usize;
716 let mut done = 0usize;
717 for &byte in &self.data {
718 let take = (n - done).min(8) as u32;
719 let v = if take < 8 {
720 u64::from(byte >> (8 - take))
721 } else {
722 u64::from(byte)
723 };
724 w.write_bits(v, take)?;
725 done += take as usize;
726 }
727 Ok(())
728 }
729}
730
731fn parse_ext_blocks(bytes: &[u8], total_bits: usize) -> crate::error::Result<Vec<L1ExtBlock>> {
736 let mut r = BitReader::new(bytes);
737 let header_bits = (L1_EXT_BLOCK_TYPE_BITS + L1_EXT_DATA_LEN_BITS) as usize;
738 let mut blocks = Vec::new();
739 while r.bits_read() + header_bits <= total_bits {
740 blocks.push(L1ExtBlock::parse(&mut r)?);
741 }
742 Ok(blocks)
743}
744
745#[derive(Debug, Clone, PartialEq, Eq)]
751#[cfg_attr(feature = "serde", derive(serde::Serialize))]
752#[non_exhaustive]
753pub struct L1Post {
754 pub configurable: L1PostConfigurable,
756 pub dynamic_current: L1PostDynamic,
758 pub dynamic_next: Option<L1PostDynamic>,
762 pub extension: Vec<L1ExtBlock>,
764}
765
766impl L1Post {
767 pub fn to_l1_current_framed(&self) -> crate::error::Result<Vec<u8>> {
776 serialize_l1_post_framed(self)
777 }
778}
779
780pub(crate) fn parse_l1_post_from_framed(
794 framed: &[u8],
795 num_rf: u8,
796 fef_present: bool,
797) -> crate::error::Result<L1Post> {
798 let mut pos = 0usize;
799
800 let (b, _) = framed
802 .get(pos..)
803 .and_then(|s| s.split_first_chunk::<2>())
804 .ok_or(crate::Error::BufferTooShort {
805 need: pos + 2,
806 have: framed.len(),
807 what: "L1CONF_LEN",
808 })?;
809 let l1conf_len_bits = u16::from_be_bytes(*b) as usize;
810 pos += 2;
811 let l1conf_bytes = l1conf_len_bits.div_ceil(8);
812 if framed.len() < pos + l1conf_bytes {
813 return Err(crate::Error::BufferTooShort {
814 need: pos + l1conf_bytes,
815 have: framed.len(),
816 what: "L1CONF",
817 });
818 }
819 let configurable =
820 L1PostConfigurable::parse(&framed[pos..pos + l1conf_bytes], num_rf, fef_present)?;
821 pos += l1conf_bytes;
822
823 let num_plp = configurable.num_plp;
824 let num_aux = configurable.num_aux;
825
826 let (b, _) = framed
828 .get(pos..)
829 .and_then(|s| s.split_first_chunk::<2>())
830 .ok_or(crate::Error::BufferTooShort {
831 need: pos + 2,
832 have: framed.len(),
833 what: "L1DYN_CURR_LEN",
834 })?;
835 let l1dyn_len_bits = u16::from_be_bytes(*b) as usize;
836 pos += 2;
837 let l1dyn_bytes = l1dyn_len_bits.div_ceil(8);
838 if framed.len() < pos + l1dyn_bytes {
839 return Err(crate::Error::BufferTooShort {
840 need: pos + l1dyn_bytes,
841 have: framed.len(),
842 what: "L1DYN_CURR",
843 });
844 }
845 let dynamic_current = L1PostDynamic::parse(&framed[pos..pos + l1dyn_bytes], num_plp, num_aux)?;
846 pos += l1dyn_bytes;
847
848 let (b, _) = framed
850 .get(pos..)
851 .and_then(|s| s.split_first_chunk::<2>())
852 .ok_or(crate::Error::BufferTooShort {
853 need: pos + 2,
854 have: framed.len(),
855 what: "L1EXT_LEN",
856 })?;
857 let l1ext_len_bits = u16::from_be_bytes(*b) as usize;
858 pos += 2;
859 let l1ext_bytes = l1ext_len_bits.div_ceil(8);
860 if framed.len() < pos + l1ext_bytes {
861 return Err(crate::Error::BufferTooShort {
862 need: pos + l1ext_bytes,
863 have: framed.len(),
864 what: "L1EXT",
865 });
866 }
867 let extension = if l1ext_bytes > 0 {
868 parse_ext_blocks(&framed[pos..pos + l1ext_bytes], l1ext_len_bits)?
869 } else {
870 Vec::new()
871 };
872
873 Ok(L1Post {
874 configurable,
875 dynamic_current,
876 dynamic_next: None, extension,
878 })
879}
880
881fn push_framed_block<F>(out: &mut Vec<u8>, bit_len: usize, write: F) -> crate::error::Result<()>
884where
885 F: FnOnce(&mut BitWriter<'_>) -> crate::error::Result<()>,
886{
887 out.extend_from_slice(&(bit_len as u16).to_be_bytes());
888 let start = out.len();
889 out.resize(start + bit_len.div_ceil(8), 0);
890 let mut w = BitWriter::new(&mut out[start..]);
891 write(&mut w)?;
892 Ok(())
893}
894
895pub(crate) fn serialize_l1_post_framed(post: &L1Post) -> crate::error::Result<Vec<u8>> {
901 let mut out = Vec::new();
902 push_framed_block(&mut out, post.configurable.len_bits(), |w| {
903 post.configurable.serialize_bits(w)
904 })?;
905 push_framed_block(&mut out, post.dynamic_current.len_bits(), |w| {
906 post.dynamic_current.serialize_bits(w)
907 })?;
908 let ext_bits: usize = post.extension.iter().map(L1ExtBlock::bits).sum();
909 push_framed_block(&mut out, ext_bits, |w| {
910 for block in &post.extension {
911 block.write(w)?;
912 }
913 Ok(())
914 })?;
915 Ok(out)
916}
917
918#[cfg(test)]
919mod tests {
920 use super::*;
921
922 fn synthetic_conf(
923 num_rf: u8,
924 fef_present: bool,
925 num_plp: u8,
926 num_aux: u8,
927 ) -> L1PostConfigurable {
928 let rf = (0..num_rf)
929 .map(|i| RfFrequency {
930 rf_idx: i,
931 frequency: 666_000_000 + u32::from(i) * 8_000_000,
932 })
933 .collect();
934 let fef = if fef_present {
935 Some(FefInfo {
936 fef_type: 0,
937 fef_length: 100,
938 fef_interval: 4,
939 })
940 } else {
941 None
942 };
943 let plps = (0..num_plp)
944 .map(|i| PlpConfig {
945 plp_id: i,
946 plp_type: PlpType::Common,
947 plp_payload_type: PlpPayloadType::Ts,
948 ff_flag: false,
949 first_rf_idx: 0,
950 first_frame_idx: 0,
951 plp_group_id: 0,
952 plp_cod: 0,
953 plp_mod: PlpModulation::Qam16,
954 plp_rotation: false,
955 plp_fec_type: PlpFecType::Ldpc16K,
956 plp_num_blocks_max: 10,
957 frame_interval: 1,
958 time_il_length: 0,
959 time_il_type: false,
960 in_band_a_flag: false,
961 in_band_b_flag: false,
962 reserved_1: 0,
963 plp_mode: PlpMode::Normal,
964 static_flag: false,
965 static_padding_flag: false,
966 })
967 .collect();
968 let aux = (0..num_aux)
969 .map(|_| AuxConfig {
970 aux_stream_type: AuxStreamType::TxSig,
971 aux_private_conf: 0,
972 })
973 .collect();
974 L1PostConfigurable {
975 sub_slices_per_frame: 512,
976 num_plp,
977 num_aux,
978 aux_config_rfu: 0,
979 rf,
980 fef,
981 plps,
982 fef_length_msb: 0,
983 reserved_2: 0,
984 aux,
985 }
986 }
987
988 fn synthetic_dyn(num_plp: u8, num_aux: u8) -> L1PostDynamic {
989 let plps = (0..num_plp)
990 .map(|i| PlpDynamic {
991 plp_id: i,
992 plp_start: 0x1234,
993 plp_num_blocks: 5,
994 reserved_2: 0,
995 })
996 .collect();
997 let aux = (0..num_aux)
998 .map(|_| AuxDynamic { aux_private_dyn: 0 })
999 .collect();
1000 L1PostDynamic {
1001 frame_idx: 0,
1002 sub_slice_interval: 0,
1003 type_2_start: 0,
1004 l1_change_counter: 0,
1005 start_rf_idx: 0,
1006 reserved_1: 0,
1007 plps,
1008 reserved_3: 0,
1009 aux,
1010 }
1011 }
1012
1013 #[test]
1014 fn configurable_round_trip() {
1015 let conf = synthetic_conf(1, false, 1, 0);
1016 let bits = conf.len_bits();
1017 let bytes = bits.div_ceil(8);
1018 let mut buf = vec![0u8; bytes];
1019 let mut w = BitWriter::new(&mut buf);
1020 conf.serialize_bits(&mut w).unwrap();
1021 let parsed = L1PostConfigurable::parse(&buf, 1, false).unwrap();
1022 assert_eq!(conf, parsed);
1023 }
1024
1025 #[test]
1026 fn configurable_round_trip_with_fef() {
1027 let conf = synthetic_conf(1, true, 1, 0);
1028 let bits = conf.len_bits();
1029 let bytes = bits.div_ceil(8);
1030 let mut buf = vec![0u8; bytes];
1031 let mut w = BitWriter::new(&mut buf);
1032 conf.serialize_bits(&mut w).unwrap();
1033 let parsed = L1PostConfigurable::parse(&buf, 1, true).unwrap();
1034 assert_eq!(conf, parsed);
1035 }
1036
1037 #[test]
1038 fn dynamic_round_trip() {
1039 let dyn_ = synthetic_dyn(1, 0);
1040 let bits = dyn_.len_bits();
1041 let bytes = bits.div_ceil(8);
1042 let mut buf = vec![0u8; bytes];
1043 let mut w = BitWriter::new(&mut buf);
1044 dyn_.serialize_bits(&mut w).unwrap();
1045 let parsed = L1PostDynamic::parse(&buf, 1, 0).unwrap();
1046 assert_eq!(dyn_, parsed);
1047 }
1048
1049 #[test]
1050 fn plp_config_bits_constant() {
1051 assert_eq!(PlpConfig::bits(), 89);
1053 }
1054
1055 #[test]
1056 fn plp_dynamic_bits_constant() {
1057 assert_eq!(PlpDynamic::bits(), 48);
1059 }
1060
1061 #[test]
1062 fn plp_code_rate_accessor() {
1063 let plp = PlpConfig {
1064 plp_id: 0,
1065 plp_type: PlpType::Common,
1066 plp_payload_type: PlpPayloadType::Ts,
1067 ff_flag: false,
1068 first_rf_idx: 0,
1069 first_frame_idx: 0,
1070 plp_group_id: 0,
1071 plp_cod: 2, plp_mod: PlpModulation::Qam64,
1073 plp_rotation: false,
1074 plp_fec_type: PlpFecType::Ldpc64K,
1075 plp_num_blocks_max: 20,
1076 frame_interval: 1,
1077 time_il_length: 0,
1078 time_il_type: false,
1079 in_band_a_flag: false,
1080 in_band_b_flag: false,
1081 reserved_1: 0,
1082 plp_mode: PlpMode::Normal,
1083 static_flag: false,
1084 static_padding_flag: false,
1085 };
1086 assert_eq!(plp.code_rate(), PlpCodeRate::R2_3);
1087 }
1088
1089 #[test]
1090 fn configurable_header_bits() {
1091 let conf = synthetic_conf(1, false, 1, 0);
1094 assert_eq!(conf.len_bits(), 191);
1095 }
1096
1097 #[test]
1098 fn dynamic_header_bits() {
1099 let dyn_ = synthetic_dyn(1, 0);
1102 assert_eq!(dyn_.len_bits(), 127);
1103 }
1104
1105 #[test]
1106 fn l1post_framed_round_trip() {
1107 let post = L1Post {
1109 configurable: synthetic_conf(1, false, 1, 0),
1110 dynamic_current: synthetic_dyn(1, 0),
1111 dynamic_next: None,
1112 extension: Vec::new(),
1113 };
1114 let framed = post.to_l1_current_framed().unwrap();
1115 assert_eq!(framed.len(), 46);
1117 let parsed = parse_l1_post_from_framed(&framed, 1, false).unwrap();
1118 assert_eq!(post, parsed);
1119 }
1120
1121 #[test]
1122 fn l1post_framed_round_trip_with_nonaligned_ext() {
1123 let post = L1Post {
1126 configurable: synthetic_conf(2, true, 1, 1),
1127 dynamic_current: synthetic_dyn(1, 1),
1128 dynamic_next: None,
1129 extension: vec![L1ExtBlock {
1130 block_type: 0xFF,
1131 data_bit_len: 12,
1132 data: vec![0xAB, 0xC0], }],
1134 };
1135 let framed = post.to_l1_current_framed().unwrap();
1136 let parsed = parse_l1_post_from_framed(&framed, 2, true).unwrap();
1137 assert_eq!(post, parsed);
1138 }
1139}