1use crate::error::{Error, Result};
14use crate::traits::Descriptor;
15use dvb_common::{Parse, Serialize};
16
17pub const TAG: u8 = 0x77;
19const HEADER_LEN: usize = 2;
20const FIXED_LEN: usize = 3;
21
22const MPE_FEC_MAX: u8 = 0x03;
24const FRAME_SIZE_MAX: u8 = 0x07;
26const MAX_AVERAGE_RATE_MAX: u8 = 0x0F;
28const TIME_SLICE_FEC_ID_MAX: u8 = 0x0F;
30
31#[derive(Debug, Clone, PartialEq, Eq)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct TimeSliceFecIdentifierDescriptor<'a> {
35 pub time_slicing: bool,
37 pub mpe_fec: u8,
39 pub frame_size: u8,
41 pub max_burst_duration: u8,
43 pub max_average_rate: u8,
45 pub time_slice_fec_id: u8,
47 #[cfg_attr(feature = "serde", serde(borrow))]
49 pub id_selector: &'a [u8],
50}
51
52impl<'a> Parse<'a> for TimeSliceFecIdentifierDescriptor<'a> {
53 type Error = crate::error::Error;
54 fn parse(bytes: &'a [u8]) -> Result<Self> {
55 if bytes.len() < HEADER_LEN {
56 return Err(Error::BufferTooShort {
57 need: HEADER_LEN,
58 have: bytes.len(),
59 what: "TimeSliceFecIdentifierDescriptor header",
60 });
61 }
62 if bytes[0] != TAG {
63 return Err(Error::InvalidDescriptor {
64 tag: bytes[0],
65 reason: "unexpected tag for time_slice_fec_identifier_descriptor",
66 });
67 }
68 let length = bytes[1] as usize;
69 let end = HEADER_LEN + length;
70 if bytes.len() < end {
71 return Err(Error::BufferTooShort {
72 need: end,
73 have: bytes.len(),
74 what: "TimeSliceFecIdentifierDescriptor body",
75 });
76 }
77 if length < FIXED_LEN {
78 return Err(Error::InvalidDescriptor {
79 tag: TAG,
80 reason: "time_slice_fec_identifier_descriptor body shorter than 3 bytes",
81 });
82 }
83 let body = &bytes[HEADER_LEN..end];
84 let b0 = body[0];
85 let time_slicing = (b0 & 0x80) != 0;
86 let mpe_fec = (b0 >> 5) & MPE_FEC_MAX;
87 let frame_size = b0 & FRAME_SIZE_MAX;
89 let max_burst_duration = body[1];
90 let max_average_rate = (body[2] >> 4) & MAX_AVERAGE_RATE_MAX;
91 let time_slice_fec_id = body[2] & TIME_SLICE_FEC_ID_MAX;
92 let id_selector = &body[FIXED_LEN..];
93 Ok(Self {
94 time_slicing,
95 mpe_fec,
96 frame_size,
97 max_burst_duration,
98 max_average_rate,
99 time_slice_fec_id,
100 id_selector,
101 })
102 }
103}
104
105impl Serialize for TimeSliceFecIdentifierDescriptor<'_> {
106 type Error = crate::error::Error;
107 fn serialized_len(&self) -> usize {
108 HEADER_LEN + FIXED_LEN + self.id_selector.len()
109 }
110
111 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
112 if self.mpe_fec > MPE_FEC_MAX {
113 return Err(Error::InvalidDescriptor {
114 tag: TAG,
115 reason: "mpe_fec exceeds 2 bits",
116 });
117 }
118 if self.frame_size > FRAME_SIZE_MAX {
119 return Err(Error::InvalidDescriptor {
120 tag: TAG,
121 reason: "frame_size exceeds 3 bits",
122 });
123 }
124 if self.max_average_rate > MAX_AVERAGE_RATE_MAX {
125 return Err(Error::InvalidDescriptor {
126 tag: TAG,
127 reason: "max_average_rate exceeds 4 bits",
128 });
129 }
130 if self.time_slice_fec_id > TIME_SLICE_FEC_ID_MAX {
131 return Err(Error::InvalidDescriptor {
132 tag: TAG,
133 reason: "time_slice_fec_id exceeds 4 bits",
134 });
135 }
136 if FIXED_LEN + self.id_selector.len() > u8::MAX as usize {
137 return Err(Error::InvalidDescriptor {
138 tag: TAG,
139 reason: "time_slice_fec_identifier_descriptor body exceeds 255 bytes",
140 });
141 }
142 let len = self.serialized_len();
143 if buf.len() < len {
144 return Err(Error::OutputBufferTooSmall {
145 need: len,
146 have: buf.len(),
147 });
148 }
149 buf[0] = TAG;
150 buf[1] = (FIXED_LEN + self.id_selector.len()) as u8;
151 buf[2] = (u8::from(self.time_slicing) << 7)
153 | ((self.mpe_fec & MPE_FEC_MAX) << 5)
154 | 0x18
155 | (self.frame_size & FRAME_SIZE_MAX);
156 buf[3] = self.max_burst_duration;
157 buf[4] = ((self.max_average_rate & MAX_AVERAGE_RATE_MAX) << 4)
158 | (self.time_slice_fec_id & TIME_SLICE_FEC_ID_MAX);
159 buf[HEADER_LEN + FIXED_LEN..len].copy_from_slice(self.id_selector);
160 Ok(len)
161 }
162}
163
164impl<'a> Descriptor<'a> for TimeSliceFecIdentifierDescriptor<'a> {
165 const TAG: u8 = TAG;
166 fn descriptor_length(&self) -> u8 {
167 (FIXED_LEN + self.id_selector.len()) as u8
168 }
169}
170
171impl<'a> crate::traits::DescriptorDef<'a> for TimeSliceFecIdentifierDescriptor<'a> {
172 const TAG: u8 = TAG;
173 const NAME: &'static str = "TIME_SLICE_FEC_IDENTIFIER";
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn parse_no_id_selector() {
182 let b0 = 0x80 | (1 << 5) | 0x18 | 0x03;
185 let bytes = [TAG, 3, b0, 0x2A, (5 << 4) | 0x0A];
186 let d = TimeSliceFecIdentifierDescriptor::parse(&bytes).unwrap();
187 assert!(d.time_slicing);
188 assert_eq!(d.mpe_fec, 1);
189 assert_eq!(d.frame_size, 3);
190 assert_eq!(d.max_burst_duration, 0x2A);
191 assert_eq!(d.max_average_rate, 5);
192 assert_eq!(d.time_slice_fec_id, 0xA);
193 assert!(d.id_selector.is_empty());
194 }
195
196 #[test]
197 fn parse_with_id_selector() {
198 let bytes = [TAG, 5, 0x00, 0x00, 0x00, 0xAA, 0xBB];
199 let d = TimeSliceFecIdentifierDescriptor::parse(&bytes).unwrap();
200 assert!(!d.time_slicing);
201 assert_eq!(d.id_selector, &[0xAA, 0xBB]);
202 }
203
204 #[test]
205 fn parse_rejects_wrong_tag() {
206 assert!(matches!(
207 TimeSliceFecIdentifierDescriptor::parse(&[0x78, 3, 0, 0, 0]).unwrap_err(),
208 Error::InvalidDescriptor { tag: 0x78, .. }
209 ));
210 }
211
212 #[test]
213 fn parse_rejects_body_too_short() {
214 let bytes = [TAG, 2, 0, 0];
215 assert!(matches!(
216 TimeSliceFecIdentifierDescriptor::parse(&bytes).unwrap_err(),
217 Error::InvalidDescriptor { .. }
218 ));
219 }
220
221 #[test]
222 fn parse_rejects_length_overrunning_buffer() {
223 let bytes = [TAG, 5, 0, 0, 0];
224 assert!(matches!(
225 TimeSliceFecIdentifierDescriptor::parse(&bytes).unwrap_err(),
226 Error::BufferTooShort { .. }
227 ));
228 }
229
230 #[test]
231 fn serialize_round_trip() {
232 let d = TimeSliceFecIdentifierDescriptor {
233 time_slicing: true,
234 mpe_fec: 1,
235 frame_size: 2,
236 max_burst_duration: 0x10,
237 max_average_rate: 6,
238 time_slice_fec_id: 0,
239 id_selector: &[0x01, 0x02, 0x03],
240 };
241 let mut buf = vec![0u8; d.serialized_len()];
242 d.serialize_into(&mut buf).unwrap();
243 assert_eq!(TimeSliceFecIdentifierDescriptor::parse(&buf).unwrap(), d);
244 }
245
246 #[test]
247 fn serialize_rejects_frame_size_over_range() {
248 let d = TimeSliceFecIdentifierDescriptor {
249 time_slicing: false,
250 mpe_fec: 0,
251 frame_size: 0x08,
252 max_burst_duration: 0,
253 max_average_rate: 0,
254 time_slice_fec_id: 0,
255 id_selector: &[],
256 };
257 let mut buf = vec![0u8; d.serialized_len()];
258 assert!(matches!(
259 d.serialize_into(&mut buf).unwrap_err(),
260 Error::InvalidDescriptor { .. }
261 ));
262 }
263
264 #[cfg(feature = "serde")]
265 #[test]
266 fn serde_serializes_to_stable_json() {
267 let d = TimeSliceFecIdentifierDescriptor {
270 time_slicing: true,
271 mpe_fec: 1,
272 frame_size: 3,
273 max_burst_duration: 0x44,
274 max_average_rate: 7,
275 time_slice_fec_id: 0xF,
276 id_selector: &[0xDE, 0xAD],
277 };
278 let j = serde_json::to_string(&d).unwrap();
279 let _v: serde_json::Value = serde_json::from_str(&j).unwrap();
282 assert!(j.contains("time_slice_fec_id"));
283 }
284}