dvb_si/descriptors/
short_smoothing_buffer.rs1use crate::error::{Error, Result};
8use crate::traits::Descriptor;
9use dvb_common::{Parse, Serialize};
10
11pub const TAG: u8 = 0x61;
13const HEADER_LEN: usize = 2;
14const FIXED_LEN: usize = 1;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize))]
20pub struct ShortSmoothingBufferDescriptor<'a> {
21 pub sb_size: u8,
23 pub sb_leak_rate: u8,
25 pub dvb_reserved: &'a [u8],
27}
28
29impl<'a> Parse<'a> for ShortSmoothingBufferDescriptor<'a> {
30 type Error = crate::error::Error;
31 fn parse(bytes: &'a [u8]) -> Result<Self> {
32 if bytes.len() < HEADER_LEN {
33 return Err(Error::BufferTooShort {
34 need: HEADER_LEN,
35 have: bytes.len(),
36 what: "ShortSmoothingBufferDescriptor header",
37 });
38 }
39 if bytes[0] != TAG {
40 return Err(Error::InvalidDescriptor {
41 tag: bytes[0],
42 reason: "unexpected tag for short_smoothing_buffer_descriptor",
43 });
44 }
45 let length = bytes[1] as usize;
46 let end = HEADER_LEN + length;
47 if bytes.len() < end {
48 return Err(Error::BufferTooShort {
49 need: end,
50 have: bytes.len(),
51 what: "ShortSmoothingBufferDescriptor body",
52 });
53 }
54 if length < FIXED_LEN {
55 return Err(Error::InvalidDescriptor {
56 tag: TAG,
57 reason: "short_smoothing_buffer_descriptor body shorter than 1 byte",
58 });
59 }
60 let packed = bytes[HEADER_LEN];
61 let sb_size = packed >> 6; let sb_leak_rate = packed & 0x3F; let dvb_reserved = &bytes[HEADER_LEN + FIXED_LEN..end];
64 Ok(Self {
65 sb_size,
66 sb_leak_rate,
67 dvb_reserved,
68 })
69 }
70}
71
72impl Serialize for ShortSmoothingBufferDescriptor<'_> {
73 type Error = crate::error::Error;
74 fn serialized_len(&self) -> usize {
75 HEADER_LEN + FIXED_LEN + self.dvb_reserved.len()
76 }
77
78 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
79 let len = self.serialized_len();
80 let body = FIXED_LEN + self.dvb_reserved.len();
81 if body > u8::MAX as usize {
82 return Err(Error::InvalidDescriptor {
83 tag: TAG,
84 reason: "short_smoothing_buffer_descriptor body exceeds 255 bytes",
85 });
86 }
87 if buf.len() < len {
88 return Err(Error::OutputBufferTooSmall {
89 need: len,
90 have: buf.len(),
91 });
92 }
93 buf[0] = TAG;
94 buf[1] = body as u8;
95 buf[HEADER_LEN] = ((self.sb_size & 0x03) << 6) | (self.sb_leak_rate & 0x3F);
96 let tail_start = HEADER_LEN + FIXED_LEN;
97 buf[tail_start..tail_start + self.dvb_reserved.len()].copy_from_slice(self.dvb_reserved);
98 Ok(len)
99 }
100}
101
102impl<'a> Descriptor<'a> for ShortSmoothingBufferDescriptor<'a> {
103 const TAG: u8 = TAG;
104 fn descriptor_length(&self) -> u8 {
105 (FIXED_LEN + self.dvb_reserved.len()) as u8
106 }
107}
108
109impl<'a> crate::traits::DescriptorDef<'a> for ShortSmoothingBufferDescriptor<'a> {
110 const TAG: u8 = TAG;
111 const NAME: &'static str = "SHORT_SMOOTHING_BUFFER";
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn parse_extracts_packed_fields() {
120 let bytes = [TAG, 1, 0x52];
122 let d = ShortSmoothingBufferDescriptor::parse(&bytes).unwrap();
123 assert_eq!(d.sb_size, 1);
124 assert_eq!(d.sb_leak_rate, 0x12);
125 assert!(d.dvb_reserved.is_empty());
126 }
127
128 #[test]
129 fn parse_preserves_reserved_tail() {
130 let bytes = [TAG, 3, 0x52, 0xAA, 0xBB];
131 let d = ShortSmoothingBufferDescriptor::parse(&bytes).unwrap();
132 assert_eq!(d.dvb_reserved, &[0xAA, 0xBB]);
133 }
134
135 #[test]
136 fn parse_rejects_wrong_tag() {
137 let err = ShortSmoothingBufferDescriptor::parse(&[0x62, 1, 0x00]).unwrap_err();
138 assert!(matches!(err, Error::InvalidDescriptor { tag: 0x62, .. }));
139 }
140
141 #[test]
142 fn parse_rejects_short_buffer() {
143 let err = ShortSmoothingBufferDescriptor::parse(&[TAG]).unwrap_err();
144 assert!(matches!(err, Error::BufferTooShort { .. }));
145 }
146
147 #[test]
148 fn parse_rejects_empty_body() {
149 let err = ShortSmoothingBufferDescriptor::parse(&[TAG, 0]).unwrap_err();
151 assert!(matches!(err, Error::InvalidDescriptor { .. }));
152 }
153
154 #[test]
155 fn parse_rejects_length_overrun() {
156 let err = ShortSmoothingBufferDescriptor::parse(&[TAG, 3, 0x52]).unwrap_err();
158 assert!(matches!(err, Error::BufferTooShort { .. }));
159 }
160
161 #[test]
162 fn serialize_round_trip() {
163 let d = ShortSmoothingBufferDescriptor {
164 sb_size: 1,
165 sb_leak_rate: 0x2A,
166 dvb_reserved: &[0x01, 0x02, 0x03],
167 };
168 let mut buf = vec![0u8; d.serialized_len()];
169 d.serialize_into(&mut buf).unwrap();
170 let re = ShortSmoothingBufferDescriptor::parse(&buf).unwrap();
171 assert_eq!(d, re);
172 }
173
174 #[test]
175 fn serialize_rejects_too_small_buffer() {
176 let d = ShortSmoothingBufferDescriptor {
177 sb_size: 1,
178 sb_leak_rate: 1,
179 dvb_reserved: &[],
180 };
181 let mut tiny = [0u8; 2];
182 let err = d.serialize_into(&mut tiny).unwrap_err();
183 assert!(matches!(err, Error::OutputBufferTooSmall { .. }));
184 }
185
186 #[test]
187 fn serialize_rejects_over_range_body() {
188 let tail = vec![0u8; 255]; let d = ShortSmoothingBufferDescriptor {
190 sb_size: 1,
191 sb_leak_rate: 1,
192 dvb_reserved: &tail,
193 };
194 let mut buf = vec![0u8; d.serialized_len()];
195 let err = d.serialize_into(&mut buf).unwrap_err();
196 assert!(matches!(err, Error::InvalidDescriptor { tag: TAG, .. }));
197 }
198
199 #[test]
200 fn descriptor_length_matches_payload() {
201 let d = ShortSmoothingBufferDescriptor {
202 sb_size: 1,
203 sb_leak_rate: 0,
204 dvb_reserved: &[0xFF, 0xFF],
205 };
206 assert_eq!(d.descriptor_length(), 3);
207 }
208
209 #[cfg(feature = "serde")]
210 #[test]
211 fn serde_serialize_is_stable() {
212 let d = ShortSmoothingBufferDescriptor {
216 sb_size: 1,
217 sb_leak_rate: 0x3F,
218 dvb_reserved: &[0xCA, 0xFE],
219 };
220 let json = serde_json::to_string(&d).unwrap();
221 assert_eq!(json, serde_json::to_string(&d.clone()).unwrap());
222 }
223}