1use crate::any::AnySegment;
7use crate::error::{Error, Result};
8use broadcast_common::len::{need_in, need_out};
9use broadcast_common::{Parse, Serialize};
10
11pub const DATA_IDENTIFIER: u8 = 0x20;
13pub const SUBTITLE_STREAM_ID: u8 = 0x00;
15pub const SYNC_BYTE: u8 = 0x0F;
17pub const END_OF_PES_MARKER: u8 = 0xFF;
19
20const MIN_FIELD_LEN: usize = 3;
22const SEGMENT_HEADER_LEN: usize = 6;
24
25#[derive(Debug, Clone, PartialEq, Eq)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize))]
31pub struct PesDataField<'a> {
32 pub subtitle_stream_id: u8,
34 #[cfg_attr(feature = "serde", serde(borrow))]
36 pub segments: alloc::vec::Vec<AnySegment<'a>>,
37 #[cfg_attr(feature = "serde", serde(skip))]
40 pub(crate) suffix: &'a [u8],
41}
42
43impl<'a> Parse<'a> for PesDataField<'a> {
44 type Error = Error;
45
46 fn parse(bytes: &'a [u8]) -> Result<Self> {
47 need_in(bytes, MIN_FIELD_LEN, "PES_data_field")?;
48 if bytes[0] != DATA_IDENTIFIER {
49 return Err(Error::BadDataIdentifier(bytes[0]));
50 }
51 let subtitle_stream_id = bytes[1];
52 if subtitle_stream_id != SUBTITLE_STREAM_ID {
53 }
55
56 let mut pos: usize = 2;
57 let mut segments = alloc::vec::Vec::new();
58
59 while pos < bytes.len() && bytes[pos] == SYNC_BYTE {
61 if pos + SEGMENT_HEADER_LEN > bytes.len() {
62 break;
64 }
65 let segment_length = u16::from_be_bytes([bytes[pos + 4], bytes[pos + 5]]) as usize;
66 let segment_end = pos + SEGMENT_HEADER_LEN + segment_length;
67 if segment_end > bytes.len() {
68 break;
71 }
72
73 let seg_bytes = &bytes[pos..segment_end];
74 let segment_type = bytes[pos + 1];
75
76 match AnySegment::dispatch(segment_type, seg_bytes) {
77 Some(Ok(seg)) => segments.push(seg),
78 Some(Err(e)) => {
79 segments.push(AnySegment::Malformed {
87 segment_type,
88 page_id: u16::from_be_bytes([seg_bytes[2], seg_bytes[3]]),
89 data: &seg_bytes[SEGMENT_HEADER_LEN..],
90 err: e,
91 });
92 }
93 None => {
94 segments.push(AnySegment::Unknown {
96 segment_type,
97 page_id: u16::from_be_bytes([seg_bytes[2], seg_bytes[3]]),
98 data: &seg_bytes[SEGMENT_HEADER_LEN..],
99 });
100 }
101 }
102
103 pos = segment_end;
104 }
105
106 let suffix = &bytes[pos..];
108 if let [marker] = suffix
109 && *marker != END_OF_PES_MARKER
110 {
111 return Err(Error::BadEndOfPesMarker(*marker));
112 }
113
114 Ok(PesDataField {
115 subtitle_stream_id,
116 segments,
117 suffix,
118 })
119 }
120}
121
122impl Serialize for PesDataField<'_> {
123 type Error = Error;
124
125 fn serialized_len(&self) -> usize {
126 2 + self.suffix.len()
127 + self
128 .segments
129 .iter()
130 .map(|s| s.serialized_len())
131 .sum::<usize>()
132 }
133
134 fn serialize_into(&self, buf: &mut [u8]) -> core::result::Result<usize, Self::Error> {
135 let len = self.serialized_len();
136 need_out(buf, len)?;
137 buf[0] = DATA_IDENTIFIER;
138 buf[1] = self.subtitle_stream_id;
139 let mut off = 2;
140 for seg in &self.segments {
141 let seg_len = seg.serialized_len();
142 seg.serialize_into(&mut buf[off..off + seg_len])?;
143 off += seg_len;
144 }
145 buf[off..off + self.suffix.len()].copy_from_slice(self.suffix);
146 Ok(len)
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153 use broadcast_common::Serialize;
154
155 #[test]
156 fn round_trip_single_end_of_display_set() {
157 let bytes = [
158 0x20, 0x00, 0x0F, 0x80, 0x00, 0x01, 0x00, 0x00, 0xFF, ];
162 let field = PesDataField::parse(&bytes).unwrap();
163 assert_eq!(field.segments.len(), 1);
164 let out = field.try_to_bytes().unwrap();
165 assert_eq!(out, bytes);
166 }
167
168 #[test]
169 fn round_trip_multiple_segments() {
170 let bytes = [
171 0x20, 0x00, 0x0F, 0x14, 0x00, 0x01, 0x00, 0x05, 0x30, 0x02, 0xCF, 0x01, 0x1F,
173 0x0F, 0x10, 0x00, 0x01, 0x00, 0x08, 0x0A, 0x08, 0x01, 0x00, 0x00, 0x64, 0x00, 0x32,
175 0x0F, 0x80, 0x00, 0x01, 0x00, 0x00, 0xFF,
177 ];
178 let field = PesDataField::parse(&bytes).unwrap();
179 assert_eq!(field.segments.len(), 3);
180 assert_eq!(field.segments[0].name(), "DISPLAY_DEFINITION");
181 assert_eq!(field.segments[1].name(), "PAGE_COMPOSITION");
182 assert_eq!(field.segments[2].name(), "END_OF_DISPLAY_SET");
183 let out = field.try_to_bytes().unwrap();
184 assert_eq!(out, bytes);
185 }
186
187 #[test]
188 fn unknown_segment_preserved() {
189 let bytes = [
190 0x20, 0x00, 0x0F, 0xA0, 0x00, 0x01, 0x00, 0x02, 0xCA, 0xFE, 0xFF,
192 ];
193 let field = PesDataField::parse(&bytes).unwrap();
194 assert_eq!(field.segments.len(), 1);
195 assert_eq!(field.segments[0].name(), "UNKNOWN");
196 let out = field.try_to_bytes().unwrap();
197 assert_eq!(out, bytes);
198 }
199
200 #[test]
201 fn malformed_typed_segment_distinct_from_unknown() {
202 let bytes = [
211 0x20, 0x00, 0x0F, 0x80, 0x00, 0x01, 0x00, 0x02, 0xCA,
213 0xFE, 0xFF,
215 ];
216 let field = PesDataField::parse(&bytes).unwrap();
217 assert_eq!(field.segments.len(), 1);
218 assert_eq!(field.segments[0].name(), "MALFORMED");
219 assert!(!matches!(field.segments[0], AnySegment::Unknown { .. }));
220 assert!(matches!(
221 field.segments[0],
222 AnySegment::Malformed {
223 segment_type: 0x80,
224 ..
225 }
226 ));
227 let out = field.try_to_bytes().unwrap();
229 assert_eq!(out, bytes);
230 }
231
232 #[test]
233 fn bad_data_identifier() {
234 let bytes = [0x00, 0x00, 0xFF];
235 let err = PesDataField::parse(&bytes).unwrap_err();
236 assert!(matches!(err, Error::BadDataIdentifier(0x00)));
237 }
238
239 #[test]
240 fn wrong_end_marker_after_the_last_segment_is_rejected() {
241 let bytes = [
242 0x20, 0x00, 0x0F, 0x80, 0x00, 0x01, 0x00, 0x00, 0xFE, ];
246 assert_eq!(
247 PesDataField::parse(&bytes).unwrap_err(),
248 Error::BadEndOfPesMarker(0xFE)
249 );
250 }
251
252 #[test]
253 fn wrong_end_marker_with_no_segments_is_rejected() {
254 assert_eq!(
255 PesDataField::parse(&[0x20, 0x00, 0x00]).unwrap_err(),
256 Error::BadEndOfPesMarker(0x00)
257 );
258 }
259
260 #[test]
261 fn truncated_segment_still_parses_with_the_remainder_kept() {
262 let bytes = [
263 0x20, 0x00, 0x0F, 0x10, 0x00, 0x01, 0x00, 0x20, 0x01, ];
266 let field = PesDataField::parse(&bytes).unwrap();
267 assert_eq!(field.segments.len(), 0);
268 assert_eq!(field.try_to_bytes().unwrap(), bytes);
269 }
270}