dvb_si/descriptors/
registration.rs1use crate::error::{Error, Result};
8use crate::traits::Descriptor;
9use dvb_common::{Parse, Serialize};
10
11pub const TAG: u8 = 0x05;
13const HEADER_LEN: usize = 2;
14const FORMAT_IDENTIFIER_LEN: usize = 4;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize))]
24#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
25pub struct RegistrationDescriptor<'a> {
26 pub format_identifier: [u8; FORMAT_IDENTIFIER_LEN],
28 pub additional_identification_info: &'a [u8],
30}
31
32impl<'a> Parse<'a> for RegistrationDescriptor<'a> {
33 type Error = crate::error::Error;
34
35 fn parse(bytes: &'a [u8]) -> Result<Self> {
36 if bytes.len() < HEADER_LEN {
37 return Err(Error::BufferTooShort {
38 need: HEADER_LEN,
39 have: bytes.len(),
40 what: "RegistrationDescriptor header",
41 });
42 }
43 if bytes[0] != TAG {
44 return Err(Error::InvalidDescriptor {
45 tag: bytes[0],
46 reason: "unexpected tag for registration_descriptor",
47 });
48 }
49 let length = bytes[1] as usize;
50 if length < FORMAT_IDENTIFIER_LEN {
51 return Err(Error::InvalidDescriptor {
52 tag: TAG,
53 reason: "registration_descriptor length too short for format_identifier",
54 });
55 }
56 let total = HEADER_LEN + length;
57 if bytes.len() < total {
58 return Err(Error::BufferTooShort {
59 need: total,
60 have: bytes.len(),
61 what: "RegistrationDescriptor body",
62 });
63 }
64 let body = &bytes[HEADER_LEN..total];
65 let mut format_identifier = [0u8; FORMAT_IDENTIFIER_LEN];
66 format_identifier.copy_from_slice(&body[..FORMAT_IDENTIFIER_LEN]);
67 let additional_identification_info = &body[FORMAT_IDENTIFIER_LEN..];
68 Ok(Self {
69 format_identifier,
70 additional_identification_info,
71 })
72 }
73}
74
75impl Serialize for RegistrationDescriptor<'_> {
76 type Error = crate::error::Error;
77
78 fn serialized_len(&self) -> usize {
79 HEADER_LEN + FORMAT_IDENTIFIER_LEN + self.additional_identification_info.len()
80 }
81
82 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
83 let len = self.serialized_len();
84 if buf.len() < len {
85 return Err(Error::OutputBufferTooSmall {
86 need: len,
87 have: buf.len(),
88 });
89 }
90 buf[0] = TAG;
91 buf[1] = (len - HEADER_LEN) as u8;
92 buf[HEADER_LEN..HEADER_LEN + FORMAT_IDENTIFIER_LEN]
93 .copy_from_slice(&self.format_identifier);
94 buf[HEADER_LEN + FORMAT_IDENTIFIER_LEN..len]
95 .copy_from_slice(self.additional_identification_info);
96 Ok(len)
97 }
98}
99
100impl<'a> Descriptor<'a> for RegistrationDescriptor<'a> {
101 const TAG: u8 = TAG;
102
103 fn descriptor_length(&self) -> u8 {
104 (self.serialized_len() - HEADER_LEN) as u8
105 }
106}
107
108impl<'a> crate::traits::DescriptorDef<'a> for RegistrationDescriptor<'a> {
109 const TAG: u8 = TAG;
110 const NAME: &'static str = "REGISTRATION";
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn parse_format_identifier_only() {
119 let bytes = [TAG, 4, b'A', b'C', b'-', b'3'];
120 let d = RegistrationDescriptor::parse(&bytes).unwrap();
121 assert_eq!(&d.format_identifier, b"AC-3");
122 assert!(d.additional_identification_info.is_empty());
123 }
124
125 #[test]
126 fn parse_with_additional_info() {
127 let bytes = [TAG, 6, b'H', b'D', b'M', b'V', 0x01, 0x02];
128 let d = RegistrationDescriptor::parse(&bytes).unwrap();
129 assert_eq!(&d.format_identifier, b"HDMV");
130 assert_eq!(d.additional_identification_info, &[0x01, 0x02]);
131 }
132
133 #[test]
134 fn parse_rejects_wrong_tag() {
135 let err = RegistrationDescriptor::parse(&[0x06, 4, 0, 0, 0, 0]).unwrap_err();
136 assert!(matches!(err, Error::InvalidDescriptor { tag: 0x06, .. }));
137 }
138
139 #[test]
140 fn parse_rejects_short_header() {
141 let err = RegistrationDescriptor::parse(&[TAG]).unwrap_err();
142 assert!(matches!(err, Error::BufferTooShort { .. }));
143 }
144
145 #[test]
146 fn parse_rejects_length_too_short_for_format_id() {
147 let bytes = [TAG, 3, 0, 0, 0];
148 let err = RegistrationDescriptor::parse(&bytes).unwrap_err();
149 assert!(matches!(err, Error::InvalidDescriptor { tag: TAG, .. }));
150 }
151
152 #[test]
153 fn parse_rejects_length_overflow() {
154 let bytes = [TAG, 10, 0, 0, 0, 0];
155 let err = RegistrationDescriptor::parse(&bytes).unwrap_err();
156 assert!(matches!(err, Error::BufferTooShort { .. }));
157 }
158
159 #[test]
160 fn serialize_round_trip() {
161 let d = RegistrationDescriptor {
162 format_identifier: *b"dtsx",
163 additional_identification_info: &[0xAA, 0xBB],
164 };
165 let mut buf = vec![0u8; d.serialized_len()];
166 d.serialize_into(&mut buf).unwrap();
167 let reparsed = RegistrationDescriptor::parse(&buf).unwrap();
168 assert_eq!(d, reparsed);
169 }
170
171 #[test]
172 fn serialize_rejects_small_buffer() {
173 let d = RegistrationDescriptor {
174 format_identifier: *b"AC-3",
175 additional_identification_info: &[],
176 };
177 let mut tiny = vec![0u8; 3];
178 let err = d.serialize_into(&mut tiny).unwrap_err();
179 assert!(matches!(err, Error::OutputBufferTooSmall { .. }));
180 }
181
182 #[test]
183 fn descriptor_length_matches_payload() {
184 let d = RegistrationDescriptor {
185 format_identifier: *b"AC-3",
186 additional_identification_info: &[0x01],
187 };
188 assert_eq!(d.descriptor_length(), 5);
189 }
190}