1use crate::any::AnySegment;
7use crate::error::{Error, Result};
8use broadcast_common::{Parse, Serialize};
9
10pub const DATA_IDENTIFIER: u8 = 0x20;
12pub const SUBTITLE_STREAM_ID: u8 = 0x00;
14pub const SYNC_BYTE: u8 = 0x0F;
16pub const END_OF_PES_MARKER: u8 = 0xFF;
18
19const MIN_FIELD_LEN: usize = 3;
21const SEGMENT_HEADER_LEN: usize = 6;
23
24#[derive(Debug, Clone, PartialEq, Eq)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize))]
30pub struct PesDataField<'a> {
31 pub subtitle_stream_id: u8,
33 #[cfg_attr(feature = "serde", serde(borrow))]
35 pub segments: alloc::vec::Vec<AnySegment<'a>>,
36 #[cfg_attr(feature = "serde", serde(skip))]
39 pub(crate) suffix: &'a [u8],
40}
41
42impl<'a> Parse<'a> for PesDataField<'a> {
43 type Error = Error;
44
45 fn parse(bytes: &'a [u8]) -> Result<Self> {
46 if bytes.len() < MIN_FIELD_LEN {
47 return Err(Error::BufferTooShort {
48 need: MIN_FIELD_LEN,
49 have: bytes.len(),
50 what: "PES_data_field",
51 });
52 }
53 if bytes[0] != DATA_IDENTIFIER {
54 return Err(Error::BadDataIdentifier(bytes[0]));
55 }
56 let subtitle_stream_id = bytes[1];
57 if subtitle_stream_id != SUBTITLE_STREAM_ID {
58 }
60
61 let mut pos: usize = 2;
62 let mut segments = alloc::vec::Vec::new();
63
64 while pos < bytes.len() && bytes[pos] == SYNC_BYTE {
66 if pos + SEGMENT_HEADER_LEN > bytes.len() {
67 break;
69 }
70 let segment_length = u16::from_be_bytes([bytes[pos + 4], bytes[pos + 5]]) as usize;
71 let segment_end = pos + SEGMENT_HEADER_LEN + segment_length;
72 if segment_end > bytes.len() {
73 break;
76 }
77
78 let seg_bytes = &bytes[pos..segment_end];
79 let segment_type = bytes[pos + 1];
80
81 match AnySegment::dispatch(segment_type, seg_bytes) {
82 Some(Ok(seg)) => segments.push(seg),
83 Some(Err(e)) => {
84 segments.push(AnySegment::Malformed {
92 segment_type,
93 page_id: u16::from_be_bytes([seg_bytes[2], seg_bytes[3]]),
94 data: &seg_bytes[SEGMENT_HEADER_LEN..],
95 err: e,
96 });
97 }
98 None => {
99 segments.push(AnySegment::Unknown {
101 segment_type,
102 page_id: u16::from_be_bytes([seg_bytes[2], seg_bytes[3]]),
103 data: &seg_bytes[SEGMENT_HEADER_LEN..],
104 });
105 }
106 }
107
108 pos = segment_end;
109 }
110
111 let suffix = &bytes[pos..];
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 if buf.len() < len {
137 return Err(Error::BufferTooShort {
138 need: len,
139 have: buf.len(),
140 what: "PES_data_field serialize",
141 });
142 }
143 buf[0] = DATA_IDENTIFIER;
144 buf[1] = self.subtitle_stream_id;
145 let mut off = 2;
146 for seg in &self.segments {
147 let seg_len = seg.serialized_len();
148 seg.serialize_into(&mut buf[off..off + seg_len])?;
149 off += seg_len;
150 }
151 buf[off..off + self.suffix.len()].copy_from_slice(self.suffix);
152 Ok(len)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use broadcast_common::Serialize;
160
161 #[test]
162 fn round_trip_single_end_of_display_set() {
163 let bytes = [
164 0x20, 0x00, 0x0F, 0x80, 0x00, 0x01, 0x00, 0x00, 0xFF, ];
168 let field = PesDataField::parse(&bytes).unwrap();
169 assert_eq!(field.segments.len(), 1);
170 let out = field.to_bytes();
171 assert_eq!(out, bytes);
172 }
173
174 #[test]
175 fn round_trip_multiple_segments() {
176 let bytes = [
177 0x20, 0x00, 0x0F, 0x14, 0x00, 0x01, 0x00, 0x05, 0x30, 0x02, 0xCF, 0x01, 0x1F,
179 0x0F, 0x10, 0x00, 0x01, 0x00, 0x08, 0x0A, 0x08, 0x01, 0x00, 0x00, 0x64, 0x00, 0x32,
181 0x0F, 0x80, 0x00, 0x01, 0x00, 0x00, 0xFF,
183 ];
184 let field = PesDataField::parse(&bytes).unwrap();
185 assert_eq!(field.segments.len(), 3);
186 assert_eq!(field.segments[0].name(), "DISPLAY_DEFINITION");
187 assert_eq!(field.segments[1].name(), "PAGE_COMPOSITION");
188 assert_eq!(field.segments[2].name(), "END_OF_DISPLAY_SET");
189 let out = field.to_bytes();
190 assert_eq!(out, bytes);
191 }
192
193 #[test]
194 fn unknown_segment_preserved() {
195 let bytes = [
196 0x20, 0x00, 0x0F, 0xA0, 0x00, 0x01, 0x00, 0x02, 0xCA, 0xFE, 0xFF,
198 ];
199 let field = PesDataField::parse(&bytes).unwrap();
200 assert_eq!(field.segments.len(), 1);
201 assert_eq!(field.segments[0].name(), "UNKNOWN");
202 let out = field.to_bytes();
203 assert_eq!(out, bytes);
204 }
205
206 #[test]
207 fn malformed_typed_segment_distinct_from_unknown() {
208 let bytes = [
217 0x20, 0x00, 0x0F, 0x80, 0x00, 0x01, 0x00, 0x02, 0xCA,
219 0xFE, 0xFF,
221 ];
222 let field = PesDataField::parse(&bytes).unwrap();
223 assert_eq!(field.segments.len(), 1);
224 assert_eq!(field.segments[0].name(), "MALFORMED");
225 assert!(!matches!(field.segments[0], AnySegment::Unknown { .. }));
226 assert!(matches!(
227 field.segments[0],
228 AnySegment::Malformed {
229 segment_type: 0x80,
230 ..
231 }
232 ));
233 let out = field.to_bytes();
235 assert_eq!(out, bytes);
236 }
237
238 #[test]
239 fn bad_data_identifier() {
240 let bytes = [0x00, 0x00, 0xFF];
241 let err = PesDataField::parse(&bytes).unwrap_err();
242 assert!(matches!(err, Error::BadDataIdentifier(0x00)));
243 }
244
245 #[test]
246 fn no_end_marker_is_ok() {
247 let bytes = [0x20, 0x00, 0x00];
249 let field = PesDataField::parse(&bytes).unwrap();
250 assert_eq!(field.segments.len(), 0);
251 }
252}