1use crate::error::{Error, Result};
8use crate::scr::{self, Scr};
9use dvb_common::{Parse, Serialize};
10
11pub const PACK_START_CODE: u32 = 0x0000_01BA;
13
14const FIXED_LEN: usize = 14;
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize))]
21pub struct PackHeader<'a> {
22 pub scr: Scr,
24 pub program_mux_rate: u32,
27 pub stuffing_length: u8,
29 #[cfg_attr(feature = "serde", serde(skip))]
31 pub stuffing: &'a [u8],
32 pub reserved: u8,
34}
35
36impl<'a> PackHeader<'a> {
37 #[must_use]
39 pub fn header_len(&self) -> usize {
40 self.serialized_len()
41 }
42}
43
44impl<'a> Parse<'a> for PackHeader<'a> {
45 type Error = Error;
46
47 fn parse(b: &'a [u8]) -> Result<Self> {
48 if b.len() < FIXED_LEN {
49 return Err(Error::BufferTooShort {
50 need: FIXED_LEN,
51 have: b.len(),
52 what: "pack_header",
53 });
54 }
55
56 if u32::from_be_bytes([b[0], b[1], b[2], b[3]]) != PACK_START_CODE {
57 return Err(Error::BadPackStartCode(u32::from_be_bytes([
58 b[0], b[1], b[2], b[3],
59 ])));
60 }
61
62 let scr = scr::read_scr_field(&b[4..10], "SCR")?;
63
64 if b[12] & 0x03 != 0x03 {
75 return Err(Error::BadMarker("program_mux_rate markers"));
76 }
77
78 let program_mux_rate =
79 ((u32::from(b[10] & 0x3F) << 16) | (u32::from(b[11]) << 8) | u32::from(b[12]))
80 & 0x3F_FFFF;
81
82 if program_mux_rate == 0 {
83 return Err(Error::ZeroMuxRate);
84 }
85
86 let reserved = (b[13] >> 3) & 0x1F;
87 let stuffing_length = b[13] & 0x07;
88
89 let total = FIXED_LEN + stuffing_length as usize;
90 if b.len() < total {
91 return Err(Error::BufferTooShort {
92 need: total,
93 have: b.len(),
94 what: "pack_header stuffing bytes",
95 });
96 }
97
98 Ok(PackHeader {
99 scr,
100 program_mux_rate,
101 stuffing_length,
102 stuffing: &b[FIXED_LEN..total],
103 reserved,
104 })
105 }
106}
107
108impl Serialize for PackHeader<'_> {
109 type Error = Error;
110
111 fn serialized_len(&self) -> usize {
112 FIXED_LEN + self.stuffing_length as 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::BufferTooShort {
119 need: len,
120 have: buf.len(),
121 what: "pack_header serialize output",
122 });
123 }
124
125 buf[0..4].copy_from_slice(&PACK_START_CODE.to_be_bytes());
127
128 buf[4..10].copy_from_slice(&scr::write_scr_field(self.scr));
130
131 let mux = self.program_mux_rate & 0x3F_FFFF;
133 buf[10] = 0x40 | ((mux >> 16) & 0x3F) as u8;
135 buf[11] = ((mux >> 8) & 0xFF) as u8;
137 buf[12] = (mux & 0xFF) as u8;
139 buf[13] = (self.reserved & 0x1F) << 3 | (self.stuffing_length & 0x07);
141
142 buf[FIXED_LEN..len].fill(0xFF);
144
145 Ok(len)
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use alloc::vec;
153
154 #[test]
155 fn pack_header_round_trip_fixture_pattern() {
156 let bytes = vec![
158 0x00, 0x00, 0x01, 0xBA, 0x44, 0x00, 0x04, 0x00, 0x04, 0x01, 0x43, 0x36, 0x3B, 0xF8, ];
161 let h = PackHeader::parse(&bytes).unwrap();
162 assert_eq!(
163 h.scr,
164 Scr {
165 base: 0,
166 extension: 0,
167 }
168 );
169 assert_eq!(h.program_mux_rate, 0x03363B);
170 assert_eq!(h.stuffing_length, 0);
171 assert_eq!(h.reserved, 0x1F);
172 assert!(h.stuffing.is_empty());
173
174 let mut out = vec![0u8; h.serialized_len()];
175 h.serialize_into(&mut out).unwrap();
176 assert_eq!(&out[..], &bytes[..], "round-trip mismatch");
177
178 let h_mut = PackHeader {
180 program_mux_rate: 0x12345,
181 ..h.clone()
182 };
183 let mut out2 = vec![0u8; h_mut.serialized_len()];
184 h_mut.serialize_into(&mut out2).unwrap();
185 assert_ne!(&out[..], &out2[..]);
186 }
187
188 #[test]
189 fn pack_header_round_trip_with_stuffing() {
190 let bytes = vec![
191 0x00, 0x00, 0x01, 0xBA, 0x44, 0x00, 0x04, 0x00, 0x04, 0x01, 0x40, 0x00, 0x43,
192 0x03, 0xFF, 0xFF, 0xFF,
194 ];
195 let h = PackHeader::parse(&bytes).unwrap();
196 assert_eq!(h.program_mux_rate, 0x43);
197 assert_eq!(h.stuffing_length, 3);
198 assert_eq!(h.stuffing, &[0xFF, 0xFF, 0xFF]);
199 assert_eq!(h.reserved, 0);
200
201 let mut out = vec![0u8; h.serialized_len()];
202 h.serialize_into(&mut out).unwrap();
203 assert_eq!(&out[..], &bytes[..]);
204
205 let h2 = PackHeader::parse(&out).unwrap();
207 assert_eq!(h, h2);
208
209 let h_mut = PackHeader {
211 reserved: 0x0A,
212 ..h.clone()
213 };
214 let mut out2 = vec![0u8; h_mut.serialized_len()];
215 h_mut.serialize_into(&mut out2).unwrap();
216 assert_ne!(&out[..], &out2[..]);
217 }
218
219 #[test]
220 fn pack_header_nonzero_scr() {
221 let scr = Scr {
222 base: 0x12345678,
223 extension: 0x0AA,
224 };
225 let scr_enc = scr::write_scr_field(scr);
226 let mut b = vec![0u8; 14];
227 b[0..4].copy_from_slice(&PACK_START_CODE.to_be_bytes());
228 b[4..10].copy_from_slice(&scr_enc);
229 b[10..14].copy_from_slice(&[0x40, 0x00, 0x43, 0x00]); let h = PackHeader::parse(&b).unwrap();
232 assert_eq!(h.scr, scr);
233 assert_eq!(h.program_mux_rate, 0x43);
234
235 let mut out = vec![0u8; h.serialized_len()];
236 h.serialize_into(&mut out).unwrap();
237 assert_eq!(&out[..], &b[..]);
238 }
239}