1use crate::error::{Error, Result};
17use crate::traits::Descriptor;
18use dvb_common::{Parse, Serialize};
19
20pub const TAG: u8 = 0x63;
22const HEADER_LEN: usize = 2;
23const BODY_LEN: u8 = 8;
25const MAX_22: u32 = (1 << 22) - 1;
27const MAX_14: u16 = (1 << 14) - 1;
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32#[cfg_attr(feature = "serde", derive(serde::Serialize))]
33pub struct PartialTransportStreamDescriptor {
34 pub peak_rate: u32,
36 pub minimum_overall_smoothing_rate: u32,
38 pub maximum_overall_smoothing_buffer: u16,
40}
41
42impl<'a> Parse<'a> for PartialTransportStreamDescriptor {
43 type Error = crate::error::Error;
44 fn parse(bytes: &'a [u8]) -> Result<Self> {
45 if bytes.len() < HEADER_LEN {
46 return Err(Error::BufferTooShort {
47 need: HEADER_LEN,
48 have: bytes.len(),
49 what: "PartialTransportStreamDescriptor header",
50 });
51 }
52 if bytes[0] != TAG {
53 return Err(Error::InvalidDescriptor {
54 tag: bytes[0],
55 reason: "unexpected tag for partial_transport_stream_descriptor",
56 });
57 }
58 let length = bytes[1] as usize;
59 let total = HEADER_LEN + length;
60 if bytes.len() < total {
61 return Err(Error::BufferTooShort {
62 need: total,
63 have: bytes.len(),
64 what: "PartialTransportStreamDescriptor body",
65 });
66 }
67 if length != BODY_LEN as usize {
68 return Err(Error::InvalidDescriptor {
69 tag: TAG,
70 reason: "partial_transport_stream_descriptor length must equal 8",
71 });
72 }
73 let b = HEADER_LEN;
74 let peak_rate = (u32::from(bytes[b] & 0x3F) << 16)
76 | (u32::from(bytes[b + 1]) << 8)
77 | u32::from(bytes[b + 2]);
78 let minimum_overall_smoothing_rate = (u32::from(bytes[b + 3] & 0x3F) << 16)
79 | (u32::from(bytes[b + 4]) << 8)
80 | u32::from(bytes[b + 5]);
81 let maximum_overall_smoothing_buffer =
83 (u16::from(bytes[b + 6] & 0x3F) << 8) | u16::from(bytes[b + 7]);
84 Ok(Self {
85 peak_rate,
86 minimum_overall_smoothing_rate,
87 maximum_overall_smoothing_buffer,
88 })
89 }
90}
91
92impl Serialize for PartialTransportStreamDescriptor {
93 type Error = crate::error::Error;
94 fn serialized_len(&self) -> usize {
95 HEADER_LEN + BODY_LEN as usize
96 }
97
98 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
99 if self.peak_rate > MAX_22 || self.minimum_overall_smoothing_rate > MAX_22 {
100 return Err(Error::InvalidDescriptor {
101 tag: TAG,
102 reason: "peak_rate / minimum_overall_smoothing_rate exceed 22 bits",
103 });
104 }
105 if self.maximum_overall_smoothing_buffer > MAX_14 {
106 return Err(Error::InvalidDescriptor {
107 tag: TAG,
108 reason: "maximum_overall_smoothing_buffer exceeds 14 bits",
109 });
110 }
111 let len = self.serialized_len();
112 if buf.len() < len {
113 return Err(Error::OutputBufferTooSmall {
114 need: len,
115 have: buf.len(),
116 });
117 }
118 buf[0] = TAG;
119 buf[1] = BODY_LEN;
120 let b = HEADER_LEN;
121 buf[b] = 0xC0 | ((self.peak_rate >> 16) as u8 & 0x3F);
123 buf[b + 1] = (self.peak_rate >> 8) as u8;
124 buf[b + 2] = self.peak_rate as u8;
125 buf[b + 3] = 0xC0 | ((self.minimum_overall_smoothing_rate >> 16) as u8 & 0x3F);
126 buf[b + 4] = (self.minimum_overall_smoothing_rate >> 8) as u8;
127 buf[b + 5] = self.minimum_overall_smoothing_rate as u8;
128 buf[b + 6] = 0xC0 | ((self.maximum_overall_smoothing_buffer >> 8) as u8 & 0x3F);
129 buf[b + 7] = self.maximum_overall_smoothing_buffer as u8;
130 Ok(len)
131 }
132}
133
134impl<'a> Descriptor<'a> for PartialTransportStreamDescriptor {
135 const TAG: u8 = TAG;
136 fn descriptor_length(&self) -> u8 {
137 BODY_LEN
138 }
139}
140
141impl<'a> crate::traits::DescriptorDef<'a> for PartialTransportStreamDescriptor {
142 const TAG: u8 = TAG;
143 const NAME: &'static str = "PARTIAL_TRANSPORT_STREAM";
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn parse_extracts_fields_and_ignores_reserved() {
152 let bytes = [TAG, 8, 0xC1, 0x23, 0x45, 0xCA, 0xBC, 0xDE, 0xD2, 0x34];
154 let d = PartialTransportStreamDescriptor::parse(&bytes).unwrap();
155 assert_eq!(d.peak_rate, 0x01_2345);
156 assert_eq!(d.minimum_overall_smoothing_rate, 0x0A_BCDE);
157 assert_eq!(d.maximum_overall_smoothing_buffer, 0x1234);
158 }
159
160 #[test]
161 fn parse_rejects_wrong_tag() {
162 let err = PartialTransportStreamDescriptor::parse(&[0x64, 8, 0, 0, 0, 0, 0, 0, 0, 0])
163 .unwrap_err();
164 assert!(matches!(err, Error::InvalidDescriptor { tag: 0x64, .. }));
165 }
166
167 #[test]
168 fn parse_rejects_short_buffer() {
169 let err = PartialTransportStreamDescriptor::parse(&[TAG]).unwrap_err();
170 assert!(matches!(err, Error::BufferTooShort { .. }));
171 }
172
173 #[test]
174 fn parse_rejects_truncated_body() {
175 let err = PartialTransportStreamDescriptor::parse(&[TAG, 8, 0, 0, 0, 0]).unwrap_err();
177 assert!(matches!(err, Error::BufferTooShort { .. }));
178 }
179
180 #[test]
181 fn parse_rejects_wrong_length() {
182 let err =
183 PartialTransportStreamDescriptor::parse(&[TAG, 7, 0, 0, 0, 0, 0, 0, 0]).unwrap_err();
184 assert!(matches!(err, Error::InvalidDescriptor { .. }));
185 }
186
187 #[test]
188 fn serialize_round_trip() {
189 let d = PartialTransportStreamDescriptor {
190 peak_rate: 0x0F_FFFF,
191 minimum_overall_smoothing_rate: 0x00_0001,
192 maximum_overall_smoothing_buffer: 0x2ABC,
193 };
194 let mut buf = vec![0u8; d.serialized_len()];
195 d.serialize_into(&mut buf).unwrap();
196 let re = PartialTransportStreamDescriptor::parse(&buf).unwrap();
197 assert_eq!(d, re);
198 }
199
200 #[test]
201 fn serialize_emits_reserved_ones() {
202 let d = PartialTransportStreamDescriptor {
203 peak_rate: 0,
204 minimum_overall_smoothing_rate: 0,
205 maximum_overall_smoothing_buffer: 0,
206 };
207 let mut buf = vec![0u8; d.serialized_len()];
208 d.serialize_into(&mut buf).unwrap();
209 assert_eq!(buf[2] & 0xC0, 0xC0);
211 assert_eq!(buf[5] & 0xC0, 0xC0);
212 assert_eq!(buf[8] & 0xC0, 0xC0);
213 }
214
215 #[test]
216 fn serialize_rejects_too_small_buffer() {
217 let d = PartialTransportStreamDescriptor {
218 peak_rate: 1,
219 minimum_overall_smoothing_rate: 1,
220 maximum_overall_smoothing_buffer: 1,
221 };
222 let mut tiny = [0u8; 5];
223 let err = d.serialize_into(&mut tiny).unwrap_err();
224 assert!(matches!(err, Error::OutputBufferTooSmall { .. }));
225 }
226
227 #[test]
228 fn serialize_rejects_over_range_22bit() {
229 let d = PartialTransportStreamDescriptor {
230 peak_rate: 1 << 22, minimum_overall_smoothing_rate: 0,
232 maximum_overall_smoothing_buffer: 0,
233 };
234 let mut buf = vec![0u8; d.serialized_len()];
235 let err = d.serialize_into(&mut buf).unwrap_err();
236 assert!(matches!(err, Error::InvalidDescriptor { tag: TAG, .. }));
237 }
238
239 #[test]
240 fn serialize_rejects_over_range_14bit() {
241 let d = PartialTransportStreamDescriptor {
242 peak_rate: 0,
243 minimum_overall_smoothing_rate: 0,
244 maximum_overall_smoothing_buffer: 1 << 14, };
246 let mut buf = vec![0u8; d.serialized_len()];
247 let err = d.serialize_into(&mut buf).unwrap_err();
248 assert!(matches!(err, Error::InvalidDescriptor { tag: TAG, .. }));
249 }
250
251 #[test]
252 fn descriptor_length_matches_payload() {
253 let d = PartialTransportStreamDescriptor {
254 peak_rate: 0,
255 minimum_overall_smoothing_rate: 0,
256 maximum_overall_smoothing_buffer: 0,
257 };
258 assert_eq!(d.descriptor_length(), 8);
259 }
260
261 #[cfg(feature = "serde")]
262 #[test]
263 fn serde_round_trip() {
264 let d = PartialTransportStreamDescriptor {
265 peak_rate: 0x00_1234,
266 minimum_overall_smoothing_rate: 0x00_5678,
267 maximum_overall_smoothing_buffer: 0x09AB,
268 };
269 let json = serde_json::to_string(&d).unwrap();
270 let _v: serde_json::Value = serde_json::from_str(&json).unwrap();
272 }
273}