1use std::fmt;
7
8use num_enum::TryFromPrimitive;
9
10use dvb_common::{Parse, Serialize};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[repr(u8)]
16pub enum AddressingFunctionTag {
17 TimeOffset = 0x00,
19 FrequencyOffset = 0x01,
21 Power = 0x02,
23 PrivateData = 0x03,
25 CellId = 0x04,
27 Enable = 0x05,
29 Bandwidth = 0x06,
31 AcePapr = 0x10,
33 MisoGroup = 0x11,
35 TrPapr = 0x12,
37 L1AcePapr = 0x13,
39 TxSigFefSeqNum = 0x15,
41 TxSigAuxStreamTxId = 0x16,
43 Frequency = 0x17,
45}
46
47impl From<AddressingFunctionTag> for u8 {
48 fn from(tag: AddressingFunctionTag) -> Self {
49 tag as u8
50 }
51}
52
53impl fmt::Display for AddressingFunctionTag {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 AddressingFunctionTag::TimeOffset => write!(f, "TimeOffset"),
57 AddressingFunctionTag::FrequencyOffset => write!(f, "FrequencyOffset"),
58 AddressingFunctionTag::Power => write!(f, "Power"),
59 AddressingFunctionTag::PrivateData => write!(f, "PrivateData"),
60 AddressingFunctionTag::CellId => write!(f, "CellId"),
61 AddressingFunctionTag::Enable => write!(f, "Enable"),
62 AddressingFunctionTag::Bandwidth => write!(f, "Bandwidth"),
63 AddressingFunctionTag::AcePapr => write!(f, "AcePapr"),
64 AddressingFunctionTag::MisoGroup => write!(f, "MisoGroup"),
65 AddressingFunctionTag::TrPapr => write!(f, "TrPapr"),
66 AddressingFunctionTag::L1AcePapr => write!(f, "L1AcePapr"),
67 AddressingFunctionTag::TxSigFefSeqNum => write!(f, "TxSigFefSeqNum"),
68 AddressingFunctionTag::TxSigAuxStreamTxId => write!(f, "TxSigAuxStreamTxId"),
69 AddressingFunctionTag::Frequency => write!(f, "Frequency"),
70 }
71 }
72}
73
74#[derive(Debug, Clone, PartialEq, Eq)]
76#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
77pub struct FunctionEntry<'a> {
78 pub tag: AddressingFunctionTag,
80 #[cfg_attr(feature = "serde", serde(borrow))]
82 pub raw: &'a [u8],
83}
84
85#[derive(Debug, Clone, PartialEq, Eq)]
94#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
95pub struct IndividualAddressingPayload<'a> {
96 pub rfu: u8,
98 #[cfg_attr(feature = "serde", serde(borrow))]
101 pub individual_addressing_data: &'a [u8],
102}
103
104const HEADER_LEN: usize = 2;
105
106impl<'a> Parse<'a> for IndividualAddressingPayload<'a> {
107 type Error = crate::error::Error;
108
109 fn parse(bytes: &'a [u8]) -> Result<Self, crate::error::Error> {
110 if bytes.len() < HEADER_LEN {
111 return Err(crate::Error::BufferTooShort {
112 need: HEADER_LEN,
113 have: bytes.len(),
114 what: "IndividualAddressingPayload header",
115 });
116 }
117
118 let rfu = bytes[0];
119 let individual_addressing_length = bytes[1] as usize;
120 let need = HEADER_LEN + individual_addressing_length;
122 if bytes.len() < need {
123 return Err(crate::Error::BufferTooShort {
124 need,
125 have: bytes.len(),
126 what: "IndividualAddressingPayload data",
127 });
128 }
129
130 Ok(IndividualAddressingPayload {
131 rfu,
132 individual_addressing_data: &bytes[HEADER_LEN..need],
133 })
134 }
135}
136
137impl<'a> crate::traits::PayloadDef<'a> for IndividualAddressingPayload<'a> {
138 const PACKET_TYPE: u8 = 0x21;
139 const NAME: &'static str = "INDIVIDUAL_ADDRESSING";
140}
141
142impl Serialize for IndividualAddressingPayload<'_> {
143 type Error = crate::error::Error;
144
145 fn serialized_len(&self) -> usize {
146 HEADER_LEN + self.individual_addressing_data.len()
147 }
148
149 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize, crate::error::Error> {
150 if buf.len() < self.serialized_len() {
151 return Err(crate::Error::OutputBufferTooSmall {
152 need: self.serialized_len(),
153 have: buf.len(),
154 });
155 }
156
157 if self.individual_addressing_data.len() > u8::MAX as usize {
160 return Err(crate::Error::ReservedBitsViolation {
161 field: "individual_addressing_length",
162 reason: "individual_addressing_data exceeds 255 bytes (8-bit length field)",
163 });
164 }
165
166 buf[0] = self.rfu;
167 buf[1] = self.individual_addressing_data.len() as u8;
168
169 if !self.individual_addressing_data.is_empty() {
170 buf[HEADER_LEN..HEADER_LEN + self.individual_addressing_data.len()]
171 .copy_from_slice(self.individual_addressing_data);
172 }
173
174 Ok(self.serialized_len())
175 }
176}
177
178impl fmt::Display for IndividualAddressingPayload<'_> {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 write!(
181 f,
182 "IndividualAddressing {{ rfu: 0x{:02X}, addr_data_len: {} }}",
183 self.rfu,
184 self.individual_addressing_data.len()
185 )
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 #[test]
194 fn addressing_function_tag_try_from_valid() {
195 assert_eq!(
196 AddressingFunctionTag::try_from(0x10),
197 Ok(AddressingFunctionTag::AcePapr)
198 );
199 assert_eq!(
200 AddressingFunctionTag::try_from(0x17),
201 Ok(AddressingFunctionTag::Frequency)
202 );
203 }
204
205 #[test]
206 fn addressing_function_tag_try_from_rejects_unknown() {
207 assert!(AddressingFunctionTag::try_from(0x14).is_err());
208 assert!(AddressingFunctionTag::try_from(0xFF).is_err());
209 }
210
211 #[test]
212 fn exhaustive_byte_sweep() {
213 let mut matched = 0u16;
214 for byte in 0u8..=0xFF {
215 if let Ok(v) = AddressingFunctionTag::try_from(byte) {
216 assert_eq!(v as u8, byte, "round-trip failed for {byte:#04x}");
217 matched += 1;
218 }
219 }
220 assert_eq!(matched, 14, "expected 14 matched variants");
221 }
222
223 #[test]
224 fn address_function_tag_display() {
225 assert_eq!(AddressingFunctionTag::AcePapr.to_string(), "AcePapr");
226 }
227
228 #[test]
229 fn parse_extracts_rfu_and_addressing_data() {
230 let buf = [0x00u8, 0x04, 0x00, 0x05, 0x04, 0x10];
234 let result = IndividualAddressingPayload::parse(&buf).unwrap();
235 assert_eq!(result.rfu, 0x00);
236 assert_eq!(result.individual_addressing_data, &[0x00, 0x05, 0x04, 0x10]);
237 }
238
239 #[test]
240 fn parse_preserves_rfu_byte() {
241 let buf = [0xFFu8, 0x00];
242 let result = IndividualAddressingPayload::parse(&buf).unwrap();
243 assert_eq!(result.rfu, 0xFF);
244 assert!(result.individual_addressing_data.is_empty());
245 }
246
247 #[test]
248 fn parse_rejects_short_buffer() {
249 assert!(IndividualAddressingPayload::parse(&[0x00]).is_err());
250 }
251
252 #[test]
253 fn parse_rejects_truncated_data() {
254 assert!(IndividualAddressingPayload::parse(&[0x00, 0x04, 0xAA, 0xBB]).is_err());
256 }
257
258 #[test]
259 fn serialize_round_trip() {
260 let orig = IndividualAddressingPayload {
261 rfu: 0x00,
262 individual_addressing_data: &[0x00, 0x03, 0x04, 0xDE, 0xAD],
263 };
264 let mut buf = vec![0u8; orig.serialized_len()];
265 orig.serialize_into(&mut buf).unwrap();
266 assert_eq!(buf[1], 5);
268 let parsed = IndividualAddressingPayload::parse(&buf).unwrap();
269 assert_eq!(orig, parsed);
270 }
271
272 #[test]
273 fn serialize_empty_data() {
274 let orig = IndividualAddressingPayload {
275 rfu: 0x00,
276 individual_addressing_data: &[],
277 };
278 let mut buf = vec![0u8; orig.serialized_len()];
279 orig.serialize_into(&mut buf).unwrap();
280 assert_eq!(buf, [0x00, 0x00]);
281 }
282}