1use crate::error::{Error, Result};
16use crate::traits::Descriptor;
17use dvb_common::{Parse, Serialize};
18
19pub const TAG: u8 = 0x45;
21const HEADER_LEN: usize = 2;
22const ENTRY_HEADER_LEN: usize = 2; const MAX_BODY_LEN: usize = u8::MAX as usize;
25const MAX_SERVICE_LEN: usize = u8::MAX as usize;
27
28#[derive(Debug, Clone, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31#[cfg_attr(feature = "serde", serde(bound(deserialize = "'de: 'a")))]
32pub struct VbiDataEntry<'a> {
33 pub data_service_id: u8,
37 #[cfg_attr(feature = "serde", serde(borrow))]
40 pub service_descriptor: &'a [u8],
41}
42
43#[derive(Debug, Clone, PartialEq, Eq)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46#[cfg_attr(feature = "serde", serde(bound(deserialize = "'de: 'a")))]
47pub struct VbiDataDescriptor<'a> {
48 #[cfg_attr(feature = "serde", serde(borrow))]
50 pub entries: Vec<VbiDataEntry<'a>>,
51}
52
53impl<'a> Parse<'a> for VbiDataDescriptor<'a> {
54 type Error = crate::error::Error;
55 fn parse(bytes: &'a [u8]) -> Result<Self> {
56 if bytes.len() < HEADER_LEN {
57 return Err(Error::BufferTooShort {
58 need: HEADER_LEN,
59 have: bytes.len(),
60 what: "VbiDataDescriptor header",
61 });
62 }
63 if bytes[0] != TAG {
64 return Err(Error::InvalidDescriptor {
65 tag: bytes[0],
66 reason: "unexpected tag for VBI_data_descriptor",
67 });
68 }
69 let length = bytes[1] as usize;
70 let end = HEADER_LEN + length;
71 if bytes.len() < end {
72 return Err(Error::BufferTooShort {
73 need: end,
74 have: bytes.len(),
75 what: "VbiDataDescriptor body",
76 });
77 }
78 let body = &bytes[HEADER_LEN..end];
79 let mut entries = Vec::new();
80 let mut pos = 0;
81 while pos < body.len() {
82 if pos + ENTRY_HEADER_LEN > body.len() {
83 return Err(Error::InvalidDescriptor {
84 tag: TAG,
85 reason: "truncated VBI data entry header",
86 });
87 }
88 let data_service_id = body[pos];
89 let svc_len = body[pos + 1] as usize;
90 pos += ENTRY_HEADER_LEN;
91 if pos + svc_len > body.len() {
92 return Err(Error::InvalidDescriptor {
93 tag: TAG,
94 reason: "data_service_descriptor_length exceeds descriptor body",
95 });
96 }
97 let service_descriptor = &body[pos..pos + svc_len];
98 pos += svc_len;
99 entries.push(VbiDataEntry {
100 data_service_id,
101 service_descriptor,
102 });
103 }
104 Ok(Self { entries })
105 }
106}
107
108impl Serialize for VbiDataDescriptor<'_> {
109 type Error = crate::error::Error;
110 fn serialized_len(&self) -> usize {
111 HEADER_LEN
112 + self
113 .entries
114 .iter()
115 .map(|e| ENTRY_HEADER_LEN + e.service_descriptor.len())
116 .sum::<usize>()
117 }
118
119 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
120 let len = self.serialized_len();
121 if buf.len() < len {
122 return Err(Error::OutputBufferTooSmall {
123 need: len,
124 have: buf.len(),
125 });
126 }
127 let body_len = len - HEADER_LEN;
128 if body_len > MAX_BODY_LEN {
130 return Err(Error::SectionLengthOverflow {
131 declared: body_len,
132 available: MAX_BODY_LEN,
133 });
134 }
135 buf[0] = TAG;
136 buf[1] = body_len as u8;
137 let mut pos = HEADER_LEN;
138 for e in &self.entries {
139 if e.service_descriptor.len() > MAX_SERVICE_LEN {
141 return Err(Error::InvalidDescriptor {
142 tag: TAG,
143 reason: "service_descriptor exceeds 255 bytes (8-bit length field)",
144 });
145 }
146 buf[pos] = e.data_service_id;
147 buf[pos + 1] = e.service_descriptor.len() as u8;
148 pos += ENTRY_HEADER_LEN;
149 buf[pos..pos + e.service_descriptor.len()].copy_from_slice(e.service_descriptor);
150 pos += e.service_descriptor.len();
151 }
152 Ok(len)
153 }
154}
155
156impl<'a> Descriptor<'a> for VbiDataDescriptor<'a> {
157 const TAG: u8 = TAG;
158 fn descriptor_length(&self) -> u8 {
159 (self.serialized_len() - HEADER_LEN) as u8
160 }
161}
162
163impl<'a> crate::traits::DescriptorDef<'a> for VbiDataDescriptor<'a> {
164 const TAG: u8 = TAG;
165 const NAME: &'static str = "VBI_DATA";
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn parse_single_entry() {
174 let bytes = [TAG, 4, 0x01, 0x02, 0xC1, 0xC2];
176 let d = VbiDataDescriptor::parse(&bytes).unwrap();
177 assert_eq!(d.entries.len(), 1);
178 assert_eq!(d.entries[0].data_service_id, 0x01);
179 assert_eq!(d.entries[0].service_descriptor, &[0xC1, 0xC2]);
180 }
181
182 #[test]
183 fn parse_multiple_entries() {
184 let bytes = [TAG, 7, 0x04, 0x01, 0xAA, 0x05, 0x02, 0xBB, 0xCC];
185 let d = VbiDataDescriptor::parse(&bytes).unwrap();
186 assert_eq!(d.entries.len(), 2);
187 assert_eq!(d.entries[0].data_service_id, 0x04);
188 assert_eq!(d.entries[0].service_descriptor, &[0xAA]);
189 assert_eq!(d.entries[1].data_service_id, 0x05);
190 assert_eq!(d.entries[1].service_descriptor, &[0xBB, 0xCC]);
191 }
192
193 #[test]
194 fn parse_entry_with_empty_service_block() {
195 let bytes = [TAG, 2, 0x06, 0x00];
196 let d = VbiDataDescriptor::parse(&bytes).unwrap();
197 assert_eq!(d.entries.len(), 1);
198 assert!(d.entries[0].service_descriptor.is_empty());
199 }
200
201 #[test]
202 fn parse_rejects_wrong_tag() {
203 assert!(matches!(
204 VbiDataDescriptor::parse(&[0x46, 0]).unwrap_err(),
205 Error::InvalidDescriptor { tag: 0x46, .. }
206 ));
207 }
208
209 #[test]
210 fn parse_rejects_short_buffer() {
211 let bytes = [TAG, 4, 0x01, 0x02];
213 assert!(matches!(
214 VbiDataDescriptor::parse(&bytes).unwrap_err(),
215 Error::BufferTooShort { .. }
216 ));
217 }
218
219 #[test]
220 fn parse_rejects_inner_length_overrun() {
221 let bytes = [TAG, 3, 0x01, 0x05, 0xAA];
223 assert!(matches!(
224 VbiDataDescriptor::parse(&bytes).unwrap_err(),
225 Error::InvalidDescriptor { tag: TAG, .. }
226 ));
227 }
228
229 #[test]
230 fn empty_descriptor_valid() {
231 let d = VbiDataDescriptor::parse(&[TAG, 0]).unwrap();
232 assert!(d.entries.is_empty());
233 }
234
235 #[test]
236 fn serialize_round_trip() {
237 let d = VbiDataDescriptor {
238 entries: vec![
239 VbiDataEntry {
240 data_service_id: 0x01,
241 service_descriptor: &[0xC1, 0xC2, 0xC3],
242 },
243 VbiDataEntry {
244 data_service_id: 0x04,
245 service_descriptor: &[],
246 },
247 ],
248 };
249 let mut buf = vec![0u8; d.serialized_len()];
250 d.serialize_into(&mut buf).unwrap();
251 assert_eq!(VbiDataDescriptor::parse(&buf).unwrap(), d);
252 }
253
254 #[test]
255 fn serialize_rejects_small_buffer() {
256 let d = VbiDataDescriptor {
257 entries: vec![VbiDataEntry {
258 data_service_id: 0x01,
259 service_descriptor: &[0xAA],
260 }],
261 };
262 let mut tiny = [0u8; 3];
263 assert!(matches!(
264 d.serialize_into(&mut tiny).unwrap_err(),
265 Error::OutputBufferTooSmall { .. }
266 ));
267 }
268
269 #[cfg(feature = "serde")]
270 #[test]
271 fn serde_serialize_stable() {
272 let make = || VbiDataDescriptor {
277 entries: vec![VbiDataEntry {
278 data_service_id: 0x01,
279 service_descriptor: &[0xC1, 0xC2],
280 }],
281 };
282 let json = serde_json::to_string(&make()).unwrap();
283 assert!(json.contains("data_service_id"));
284 assert_eq!(json, serde_json::to_string(&make()).unwrap());
285 }
286}