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