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