1use crate::error::{Error, Result};
9use crate::traits::Table;
10use dvb_common::{Parse, Serialize};
11
12pub const TABLE_ID: u8 = 0x72;
14pub const PID: u16 = 0x0014;
16
17const HEADER_LEN: usize = 3;
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize))]
22pub struct St {
23 pub payload: Vec<u8>,
25}
26
27impl St {
28 #[inline]
30 #[must_use]
31 pub fn new(payload: Vec<u8>) -> Self {
32 Self { payload }
33 }
34
35 #[inline]
37 #[must_use]
38 pub fn len(&self) -> usize {
39 self.payload.len()
40 }
41
42 #[inline]
44 #[must_use]
45 pub fn is_empty(&self) -> bool {
46 self.payload.is_empty()
47 }
48}
49
50impl<'a> Parse<'a> for St {
51 type Error = crate::error::Error;
52
53 fn parse(bytes: &'a [u8]) -> Result<Self> {
54 if bytes.len() < HEADER_LEN {
55 return Err(Error::BufferTooShort {
56 need: HEADER_LEN,
57 have: bytes.len(),
58 what: "St",
59 });
60 }
61
62 if bytes[0] != TABLE_ID {
63 return Err(Error::UnexpectedTableId {
64 table_id: bytes[0],
65 what: "St",
66 expected: &[TABLE_ID],
67 });
68 }
69
70 let section_length = ((bytes[1] & 0x0F) as u16) << 8 | bytes[2] as u16;
71 let payload_len = section_length as usize;
72
73 if bytes.len() < HEADER_LEN + payload_len {
74 return Err(Error::BufferTooShort {
75 need: HEADER_LEN + payload_len,
76 have: bytes.len(),
77 what: "St payload",
78 });
79 }
80
81 let payload = &bytes[HEADER_LEN..HEADER_LEN + payload_len];
84 Ok(Self {
85 payload: payload.to_vec(),
86 })
87 }
88}
89
90impl Serialize for St {
91 type Error = crate::error::Error;
92
93 fn serialized_len(&self) -> usize {
94 HEADER_LEN + self.payload.len()
95 }
96
97 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
98 let len = self.serialized_len();
99 if buf.len() < len {
100 return Err(Error::OutputBufferTooSmall {
101 need: len,
102 have: buf.len(),
103 });
104 }
105
106 buf[0] = TABLE_ID;
108
109 buf[1] = 0x70 | ((self.payload.len() >> 8) as u8 & 0x0F);
112
113 buf[2] = (self.payload.len() & 0xFF) as u8;
115
116 buf[HEADER_LEN..len].copy_from_slice(&self.payload);
118
119 Ok(len)
120 }
121}
122
123impl<'a> Table<'a> for St {
124 const TABLE_ID: u8 = TABLE_ID;
125 const PID: u16 = PID;
126}
127
128impl<'a> crate::traits::TableDef<'a> for St {
129 const TABLE_ID_RANGES: &'static [(u8, u8)] = &[(TABLE_ID, TABLE_ID)];
130 const NAME: &'static str = "STUFFING";
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 fn make_st_section(payload: &[u8]) -> Vec<u8> {
139 let mut buf = vec![TABLE_ID, 0x70, payload.len() as u8];
140 buf.extend_from_slice(payload);
141 buf
142 }
143
144 #[test]
145 fn parse_rejects_wrong_tag() {
146 let bytes = [0x71, 0x70, 0x02, 0x00, 0x00];
147 assert!(matches!(
148 St::parse(&bytes).unwrap_err(),
149 Error::UnexpectedTableId { table_id: 0x71, .. }
150 ));
151 }
152
153 #[test]
154 fn parse_empty_payload() {
155 let bytes = make_st_section(&[]);
156 let st = St::parse(&bytes).unwrap();
157 assert!(st.is_empty());
158 }
159
160 #[test]
163 fn parse_accepts_any_data_byte_value() {
164 let bytes = make_st_section(&[0x00, 0xFF, 0xAA]);
165 let st = St::parse(&bytes).unwrap();
166 assert_eq!(st.payload, vec![0x00, 0xFF, 0xAA]);
167 let mut buf = vec![0u8; st.serialized_len()];
168 st.serialize_into(&mut buf).unwrap();
169 assert_eq!(buf, bytes);
170 }
171
172 #[test]
173 fn serialize_writes_correct_header() {
174 let st = St::new(vec![0x00, 0x00]);
175 let mut buf = vec![0u8; st.serialized_len()];
176 st.serialize_into(&mut buf).unwrap();
177 assert_eq!(buf[0], TABLE_ID);
178 assert_eq!(buf[1], 0x70 | ((2 >> 8) as u8 & 0x0F));
179 assert_eq!(buf[2], 2);
180 }
181
182 #[test]
183 fn serialize_empty_payload() {
184 let st = St::new(vec![]);
185 let mut buf = vec![0u8; st.serialized_len()];
186 st.serialize_into(&mut buf).unwrap();
187 assert_eq!(buf, [TABLE_ID, 0x70, 0x00]);
188 }
189
190 #[test]
191 fn serialize_rejects_too_small_buffer() {
192 let st = St::new(vec![0x00]);
193 let mut too_small = vec![0u8; st.serialized_len() - 1];
194 let err = st.serialize_into(&mut too_small).unwrap_err();
195 assert!(matches!(err, Error::OutputBufferTooSmall { .. }));
196 }
197
198 #[test]
199 fn round_trip_preserves_all_fields() {
200 let st = St::new(vec![0x00, 0x00, 0x00]);
201 let mut buf = vec![0u8; st.serialized_len()];
202 st.serialize_into(&mut buf).unwrap();
203 let re = St::parse(&buf).unwrap();
204 assert_eq!(st, re);
205 }
206
207 #[test]
208 fn round_trip_empty() {
209 let st = St::new(vec![]);
210 let mut buf = vec![0u8; st.serialized_len()];
211 st.serialize_into(&mut buf).unwrap();
212 let re = St::parse(&buf).unwrap();
213 assert_eq!(st, re);
214 }
215
216 #[test]
217 fn round_trip_many_stuffs() {
218 let st = St::new(vec![0x00; 185]);
219 let mut buf = vec![0u8; st.serialized_len()];
220 st.serialize_into(&mut buf).unwrap();
221 let re = St::parse(&buf).unwrap();
222 assert_eq!(st, re);
223 }
224
225 #[test]
226 fn parse_rejects_buffer_too_short() {
227 let bytes = [0x72, 0x70]; assert!(matches!(
229 St::parse(&bytes).unwrap_err(),
230 Error::BufferTooShort { need: 3, .. }
231 ));
232 }
233
234 #[test]
235 fn parse_rejects_section_length_exceeds_buffer() {
236 let bytes = [0x72, 0x70, 10, 0x00, 0x00];
238 assert!(matches!(
239 St::parse(&bytes).unwrap_err(),
240 Error::BufferTooShort {
241 what: "St payload",
242 ..
243 }
244 ));
245 }
246
247 #[test]
248 fn table_trait_constants() {
249 assert_eq!(<St as Table>::TABLE_ID, 0x72);
250 assert_eq!(<St as Table>::PID, 0x0014);
251 }
252
253 #[test]
254 fn serialized_len_matches_wire_size() {
255 let st = St::new(vec![0x00; 50]);
256 assert_eq!(st.serialized_len(), HEADER_LEN + 50);
257 }
258
259 #[test]
260 fn to_bytes_produces_valid_section() {
261 let st = St::new(vec![0x00, 0x00]);
262 let bytes = st.to_bytes();
263 assert_eq!(bytes[0], TABLE_ID);
264 assert_eq!(bytes.len(), st.serialized_len());
265 }
266
267 #[test]
268 fn len_and_is_empty() {
269 let empty = St::new(vec![]);
270 assert!(empty.is_empty());
271 assert_eq!(empty.len(), 0);
272
273 let filled = St::new(vec![0x00; 10]);
274 assert!(!filled.is_empty());
275 assert_eq!(filled.len(), 10);
276 }
277
278 #[test]
279 fn new_constructor() {
280 let st = St::new(vec![0x00]);
281 assert_eq!(st.len(), 1);
282 }
283}