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