dvb_si/descriptors/
ac3.rs1use super::descriptor_body;
8use crate::error::{Error, Result};
9use dvb_common::{Parse, Serialize};
10
11pub const TAG: u8 = 0x6A;
13const HEADER_LEN: usize = 2;
14
15const FLAG_COMPONENT_TYPE: u8 = 0x80;
16const FLAG_BSID: u8 = 0x40;
17const FLAG_MAINID: u8 = 0x20;
18const FLAG_ASVC: u8 = 0x10;
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize))]
23#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
24pub struct Ac3Descriptor<'a> {
25 pub component_type: Option<u8>,
27 pub bsid: Option<u8>,
29 pub mainid: Option<u8>,
31 pub asvc: Option<u8>,
33 pub additional_info: &'a [u8],
35}
36
37impl<'a> Parse<'a> for Ac3Descriptor<'a> {
38 type Error = crate::error::Error;
39 fn parse(bytes: &'a [u8]) -> Result<Self> {
40 let body = descriptor_body(
41 bytes,
42 TAG,
43 "Ac3Descriptor",
44 "unexpected tag for AC-3 descriptor",
45 )?;
46 if body.is_empty() {
47 return Err(Error::InvalidDescriptor {
48 tag: TAG,
49 reason: "descriptor body is empty (length=0)",
50 });
51 }
52 let flags = body[0];
53 let mut pos = 1;
54 let mut read_one = |set: bool| -> Result<Option<u8>> {
55 if !set {
56 return Ok(None);
57 }
58 if pos >= body.len() {
59 return Err(Error::InvalidDescriptor {
60 tag: TAG,
61 reason: "AC-3 descriptor flags claim more bytes than length permits",
62 });
63 }
64 let b = body[pos];
65 pos += 1;
66 Ok(Some(b))
67 };
68
69 let component_type = read_one(flags & FLAG_COMPONENT_TYPE != 0)?;
70 let bsid = read_one(flags & FLAG_BSID != 0)?;
71 let mainid = read_one(flags & FLAG_MAINID != 0)?;
72 let asvc = read_one(flags & FLAG_ASVC != 0)?;
73 let additional_info = &body[pos..];
74 Ok(Self {
75 component_type,
76 bsid,
77 mainid,
78 asvc,
79 additional_info,
80 })
81 }
82}
83
84impl Serialize for Ac3Descriptor<'_> {
85 type Error = crate::error::Error;
86 fn serialized_len(&self) -> usize {
87 HEADER_LEN
88 + 1
89 + usize::from(self.component_type.is_some())
90 + usize::from(self.bsid.is_some())
91 + usize::from(self.mainid.is_some())
92 + usize::from(self.asvc.is_some())
93 + self.additional_info.len()
94 }
95
96 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
97 let len = self.serialized_len();
98 if buf.len() < len {
99 return Err(Error::OutputBufferTooSmall {
100 need: len,
101 have: buf.len(),
102 });
103 }
104 buf[0] = TAG;
105 buf[1] = (len - HEADER_LEN) as u8;
106 let mut flags: u8 = 0;
107 if self.component_type.is_some() {
108 flags |= FLAG_COMPONENT_TYPE;
109 }
110 if self.bsid.is_some() {
111 flags |= FLAG_BSID;
112 }
113 if self.mainid.is_some() {
114 flags |= FLAG_MAINID;
115 }
116 if self.asvc.is_some() {
117 flags |= FLAG_ASVC;
118 }
119 buf[2] = flags | 0x0F;
121 let mut pos = 3;
122 for b in [self.component_type, self.bsid, self.mainid, self.asvc]
123 .into_iter()
124 .flatten()
125 {
126 buf[pos] = b;
127 pos += 1;
128 }
129 buf[pos..pos + self.additional_info.len()].copy_from_slice(self.additional_info);
130 Ok(len)
131 }
132}
133impl<'a> crate::traits::DescriptorDef<'a> for Ac3Descriptor<'a> {
134 const TAG: u8 = TAG;
135 const NAME: &'static str = "AC3";
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn parse_with_all_fields() {
144 let bytes = [
145 TAG,
146 5,
147 FLAG_COMPONENT_TYPE | FLAG_BSID | FLAG_MAINID | FLAG_ASVC,
148 0x11,
149 0x22,
150 0x33,
151 0x44,
152 ];
153 let d = Ac3Descriptor::parse(&bytes).unwrap();
154 assert_eq!(d.component_type, Some(0x11));
155 assert_eq!(d.bsid, Some(0x22));
156 assert_eq!(d.mainid, Some(0x33));
157 assert_eq!(d.asvc, Some(0x44));
158 assert_eq!(d.additional_info, &[] as &[u8]);
159 }
160
161 #[test]
162 fn parse_with_only_component_type() {
163 let bytes = [TAG, 2, FLAG_COMPONENT_TYPE, 0x07];
164 let d = Ac3Descriptor::parse(&bytes).unwrap();
165 assert_eq!(d.component_type, Some(0x07));
166 assert_eq!(d.bsid, None);
167 }
168
169 #[test]
170 fn parse_with_additional_info_only() {
171 let bytes = [TAG, 3, 0x00, 0xAA, 0xBB];
172 let d = Ac3Descriptor::parse(&bytes).unwrap();
173 assert_eq!(d.component_type, None);
174 assert_eq!(d.additional_info, &[0xAA, 0xBB]);
175 }
176
177 #[test]
178 fn parse_rejects_wrong_tag() {
179 assert!(matches!(
180 Ac3Descriptor::parse(&[0x7A, 1, 0]).unwrap_err(),
181 Error::InvalidDescriptor { tag: 0x7A, .. }
182 ));
183 }
184
185 #[test]
186 fn parse_rejects_flags_past_length() {
187 let bytes = [TAG, 1, FLAG_COMPONENT_TYPE];
189 assert!(matches!(
190 Ac3Descriptor::parse(&bytes).unwrap_err(),
191 Error::InvalidDescriptor { .. }
192 ));
193 }
194
195 #[test]
196 fn serialize_round_trip() {
197 let d = Ac3Descriptor {
198 component_type: Some(0x40),
199 bsid: Some(8),
200 mainid: None,
201 asvc: None,
202 additional_info: &[0xFE, 0xED],
203 };
204 let mut buf = vec![0u8; d.serialized_len()];
205 d.serialize_into(&mut buf).unwrap();
206 assert_eq!(Ac3Descriptor::parse(&buf).unwrap(), d);
207 }
208
209 #[test]
210 fn parse_rejects_empty_body() {
211 let bytes = [TAG, 0];
212 assert!(matches!(
213 Ac3Descriptor::parse(&bytes).unwrap_err(),
214 Error::InvalidDescriptor { .. }
215 ));
216 }
217}