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