dvb_si/descriptors/
bouquet_name.rs1use crate::error::{Error, Result};
4use crate::text::DvbText;
5use crate::traits::Descriptor;
6use dvb_common::{Parse, Serialize};
7
8pub const TAG: u8 = 0x47;
10
11pub const HEADER_LEN: usize = 2;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct BouquetNameDescriptor<'a> {
19 pub bouquet_name: DvbText<'a>,
21}
22
23impl<'a> Parse<'a> for BouquetNameDescriptor<'a> {
24 type Error = crate::error::Error;
25 fn parse(bytes: &'a [u8]) -> Result<Self> {
26 if bytes.len() < HEADER_LEN {
27 return Err(Error::BufferTooShort {
28 need: HEADER_LEN,
29 have: bytes.len(),
30 what: "bouquet name descriptor header",
31 });
32 }
33
34 let tag = bytes[0];
35 if tag != TAG {
36 return Err(Error::InvalidDescriptor {
37 tag,
38 reason: "expected tag 0x47",
39 });
40 }
41
42 let length = bytes[1] as usize;
43 let total = HEADER_LEN + length;
44
45 if bytes.len() < total {
46 return Err(Error::BufferTooShort {
47 need: total,
48 have: bytes.len(),
49 what: "bouquet name descriptor payload",
50 });
51 }
52
53 Ok(BouquetNameDescriptor {
54 bouquet_name: DvbText::new(&bytes[HEADER_LEN..total]),
55 })
56 }
57}
58
59impl Serialize for BouquetNameDescriptor<'_> {
60 type Error = crate::error::Error;
61 fn serialized_len(&self) -> usize {
62 HEADER_LEN + self.bouquet_name.len()
63 }
64
65 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
66 let need = self.serialized_len();
67 if buf.len() < need {
68 return Err(Error::OutputBufferTooSmall {
69 need,
70 have: buf.len(),
71 });
72 }
73
74 buf[0] = TAG;
75 buf[1] = self.bouquet_name.len() as u8;
76 buf[HEADER_LEN..need].copy_from_slice(self.bouquet_name.raw());
77
78 Ok(need)
79 }
80}
81
82impl<'a> Descriptor<'a> for BouquetNameDescriptor<'a> {
83 const TAG: u8 = 0x47;
84
85 fn descriptor_length(&self) -> u8 {
86 self.bouquet_name.raw().len() as u8
87 }
88}
89
90impl<'a> crate::traits::DescriptorDef<'a> for BouquetNameDescriptor<'a> {
91 const TAG: u8 = TAG;
92 const NAME: &'static str = "BOUQUET_NAME";
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
101 fn parse_extracts_bouquet_name() {
102 let raw: Vec<u8> = vec![
103 TAG, 0x04, b'B', b'O', b'U', b'Q',
105 ];
106 let desc = BouquetNameDescriptor::parse(&raw).unwrap();
107 assert_eq!(desc.bouquet_name.raw(), b"BOUQ");
108 }
109
110 #[test]
112 fn parse_rejects_wrong_tag() {
113 let raw: Vec<u8> = vec![
114 0x48, 0x04, b'B', b'O', b'U', b'Q',
116 ];
117 let err = BouquetNameDescriptor::parse(&raw).unwrap_err();
118 assert!(
119 matches!(err, Error::InvalidDescriptor { tag: 0x48, .. }),
120 "expected InvalidDescriptor(tag=0x48), got {err:?}"
121 );
122 }
123
124 #[test]
126 fn parse_rejects_buffer_shorter_than_header() {
127 let raw: &[u8] = &[0x47];
128 let err = BouquetNameDescriptor::parse(raw).unwrap_err();
129 assert!(
130 matches!(err, Error::BufferTooShort { need: 2, .. }),
131 "expected BufferTooShort(need=2), got {err:?}"
132 );
133 }
134
135 #[test]
137 fn parse_rejects_length_overrunning_buffer() {
138 let raw: Vec<u8> = vec![
139 0x47, 0x05, 0xAA, 0xBB, ];
142 let err = BouquetNameDescriptor::parse(&raw).unwrap_err();
143 assert!(matches!(err, Error::BufferTooShort { .. }));
144 }
145
146 #[test]
148 fn empty_bouquet_name_is_valid() {
149 let raw: &[u8] = &[TAG, 0x00];
150 let desc = BouquetNameDescriptor::parse(raw).unwrap();
151 assert!(desc.bouquet_name.raw().is_empty());
152 }
153
154 #[test]
157 fn serialize_round_trip_preserves_bytes() {
158 let raw: Vec<u8> = vec![TAG, 0x04, b'B', b'O', b'U', b'Q'];
159 let parsed = BouquetNameDescriptor::parse(&raw).unwrap();
160 let mut buf = vec![0u8; parsed.serialized_len()];
161 let written = parsed.serialize_into(&mut buf).unwrap();
162 assert_eq!(written, parsed.serialized_len());
163
164 let reparsed = BouquetNameDescriptor::parse(&buf).unwrap();
165 assert_eq!(parsed, reparsed);
166 assert_eq!(&raw, &buf[..]);
167 }
168
169 #[test]
171 fn serialize_rejects_too_small_buffer() {
172 let raw: Vec<u8> = vec![TAG, 0x04, b'B', b'O', b'U', b'Q'];
173 let parsed = BouquetNameDescriptor::parse(&raw).unwrap();
174 let mut tiny = vec![0u8; 1];
175 let err = parsed.serialize_into(&mut tiny).unwrap_err();
176 assert!(
177 matches!(err, Error::OutputBufferTooSmall { need, .. } if need == parsed.serialized_len()),
178 "expected OutputBufferTooSmall(need={}), got {err:?}",
179 parsed.serialized_len()
180 );
181 }
182}