dvb_t2mi/payload/
l1_future.rs1use dvb_common::{Parse, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize))]
17#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
18pub struct L1FuturePayload<'a> {
19 pub frame_idx: u8,
21 pub l1_future_data: &'a [u8],
23}
24
25const L1_FUTURE_HEADER_LEN: usize = 2;
26
27impl<'a> Parse<'a> for L1FuturePayload<'a> {
28 type Error = crate::error::Error;
29
30 fn parse(bytes: &'a [u8]) -> Result<Self, crate::error::Error> {
31 if bytes.len() < L1_FUTURE_HEADER_LEN {
32 return Err(crate::Error::BufferTooShort {
33 need: L1_FUTURE_HEADER_LEN,
34 have: bytes.len(),
35 what: "L1FuturePayload header",
36 });
37 }
38
39 if bytes[1] != 0 {
40 return Err(crate::Error::ReservedBitsViolation {
41 field: "byte 1 RFU",
42 reason: "Must be zero (ETSI TS 102 773 §5.2.5)",
43 });
44 }
45
46 Ok(L1FuturePayload {
47 frame_idx: bytes[0],
48 l1_future_data: &bytes[L1_FUTURE_HEADER_LEN..],
49 })
50 }
51}
52
53impl<'a> crate::traits::PayloadDef<'a> for L1FuturePayload<'a> {
54 const PACKET_TYPE: u8 = 0x11;
55 const NAME: &'static str = "L1_FUTURE";
56}
57
58impl Serialize for L1FuturePayload<'_> {
59 type Error = crate::error::Error;
60
61 fn serialized_len(&self) -> usize {
62 L1_FUTURE_HEADER_LEN + self.l1_future_data.len()
63 }
64
65 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, crate::error::Error> {
66 if buf.len() < self.serialized_len() {
67 return Err(crate::Error::OutputBufferTooSmall {
68 need: self.serialized_len(),
69 have: buf.len(),
70 });
71 }
72
73 buf[0] = self.frame_idx;
74 buf[1] = 0; if !self.l1_future_data.is_empty() {
77 buf[L1_FUTURE_HEADER_LEN..L1_FUTURE_HEADER_LEN + self.l1_future_data.len()]
78 .copy_from_slice(self.l1_future_data);
79 }
80
81 Ok(self.serialized_len())
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn parse_extracts_frame_idx() {
91 let buf = [0xABu8, 0x00, 0x12, 0x34];
92 let result = L1FuturePayload::parse(&buf).unwrap();
93 assert_eq!(result.frame_idx, 0xAB);
94 assert_eq!(result.l1_future_data, &[0x12, 0x34]);
95 }
96
97 #[test]
98 fn parse_rejects_nonzero_rfu() {
99 let buf = [0x00u8, 0x01, 0x00];
100 assert!(L1FuturePayload::parse(&buf).is_err());
101 }
102
103 #[test]
104 fn parse_rejects_short_buffer() {
105 assert!(L1FuturePayload::parse(&[0x00]).is_err());
106 }
107
108 #[test]
109 fn serialize_round_trip() {
110 let orig = L1FuturePayload {
111 frame_idx: 0x42,
112 l1_future_data: &[0xCA, 0xFE, 0xBA, 0xBE],
113 };
114 let mut buf = vec![0u8; orig.serialized_len()];
115 orig.serialize_into(&mut buf).unwrap();
116 let parsed = L1FuturePayload::parse(&buf).unwrap();
117 assert_eq!(orig, parsed);
118 }
119
120 #[test]
121 fn empty_future_data() {
122 let buf = [0x05u8, 0x00];
123 let result = L1FuturePayload::parse(&buf).unwrap();
124 assert!(result.l1_future_data.is_empty());
125 }
126}