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