Skip to main content

dvb_si/descriptors/
network_name.rs

1//! Network Name Descriptor — ETSI EN 300 468 §6.2.28 (tag 0x40).
2
3use crate::error::{Error, Result};
4use crate::text::DvbText;
5use dvb_common::{Parse, Serialize};
6
7use super::descriptor_body;
8
9/// Wire tag for the Network Name Descriptor.
10pub const TAG: u8 = 0x40;
11
12/// Header length (tag byte + length byte, no payload).
13pub const HEADER_LEN: usize = 2;
14
15/// Network Name Descriptor (tag 0x40). Carries the human-readable name of
16/// a DVB network in its NIT's `network_descriptors_loop`.
17#[derive(Debug, Clone, PartialEq, Eq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize))]
19#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
20pub struct NetworkNameDescriptor<'a> {
21    /// DVB Annex-A encoded network name (EN 300 468 §6.2.28).
22    pub network_name: DvbText<'a>,
23}
24
25impl<'a> Parse<'a> for NetworkNameDescriptor<'a> {
26    type Error = crate::error::Error;
27    fn parse(bytes: &'a [u8]) -> Result<Self> {
28        let body = descriptor_body(
29            bytes,
30            TAG,
31            "NetworkNameDescriptor",
32            "unexpected tag for network_name_descriptor",
33        )?;
34        Ok(NetworkNameDescriptor {
35            network_name: DvbText::new(body),
36        })
37    }
38}
39
40impl Serialize for NetworkNameDescriptor<'_> {
41    type Error = crate::error::Error;
42    fn serialized_len(&self) -> usize {
43        HEADER_LEN + self.network_name.len()
44    }
45
46    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
47        let need = self.serialized_len();
48        if buf.len() < need {
49            return Err(Error::OutputBufferTooSmall {
50                need,
51                have: buf.len(),
52            });
53        }
54
55        buf[0] = TAG;
56        buf[1] = self.network_name.len() as u8;
57        buf[HEADER_LEN..need].copy_from_slice(self.network_name.raw());
58
59        Ok(need)
60    }
61}
62impl<'a> crate::traits::DescriptorDef<'a> for NetworkNameDescriptor<'a> {
63    const TAG: u8 = TAG;
64    const NAME: &'static str = "NETWORK_NAME";
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    /// Encode a 4-byte name, confirm parse extracts it.
72    #[test]
73    fn parse_extracts_network_name() {
74        let raw: Vec<u8> = vec![
75            TAG, 0x04, // length = 4
76            b'E', b'U', b'T', b'E',
77        ];
78        let desc = NetworkNameDescriptor::parse(&raw).unwrap();
79        assert_eq!(desc.network_name.raw(), b"EUTE");
80    }
81
82    /// Wrong tag byte should return InvalidDescriptor.
83    #[test]
84    fn parse_rejects_wrong_tag() {
85        let raw: Vec<u8> = vec![
86            0x41, // wrong tag
87            0x04, b'E', b'U', b'T', b'E',
88        ];
89        let err = NetworkNameDescriptor::parse(&raw).unwrap_err();
90        assert!(
91            matches!(err, Error::InvalidDescriptor { tag: 0x41, .. }),
92            "expected InvalidDescriptor(tag=0x41), got {err:?}"
93        );
94    }
95
96    /// Only the tag byte — too short for the 2-byte header.
97    #[test]
98    fn parse_rejects_buffer_shorter_than_header() {
99        let raw: &[u8] = &[0x40];
100        let err = NetworkNameDescriptor::parse(raw).unwrap_err();
101        assert!(
102            matches!(err, Error::BufferTooShort { need: 2, .. }),
103            "expected BufferTooShort(need=2), got {err:?}"
104        );
105    }
106
107    /// Length byte says 5 but only 2 bytes follow — mismatch.
108    #[test]
109    fn parse_rejects_length_byte_overflowing_buffer() {
110        let raw: Vec<u8> = vec![
111            0x40, 0x05, // claims 5 bytes follow
112            0xAA, 0xBB, // only 2 bytes available
113        ];
114        let err = NetworkNameDescriptor::parse(&raw).unwrap_err();
115        assert!(matches!(err, Error::BufferTooShort { .. }));
116    }
117
118    /// Parse → serialize → re-parse should yield an equal struct and
119    /// identical bytes.
120    #[test]
121    fn serialize_round_trip_preserves_bytes() {
122        let raw: Vec<u8> = vec![TAG, 0x04, b'E', b'U', b'T', b'E'];
123        let parsed = NetworkNameDescriptor::parse(&raw).unwrap();
124        let mut buf = vec![0u8; parsed.serialized_len()];
125        let written = parsed.serialize_into(&mut buf).unwrap();
126        assert_eq!(written, parsed.serialized_len());
127
128        let reparsed = NetworkNameDescriptor::parse(&buf).unwrap();
129        assert_eq!(parsed, reparsed);
130        assert_eq!(&raw, &buf[..]);
131    }
132
133    /// Serialise into a buffer smaller than `serialized_len()` must fail.
134    #[test]
135    fn serialize_rejects_too_small_buffer() {
136        let raw: Vec<u8> = vec![TAG, 0x04, b'E', b'U', b'T', b'E'];
137        let parsed = NetworkNameDescriptor::parse(&raw).unwrap();
138        let mut tiny = vec![0u8; 1];
139        let err = parsed.serialize_into(&mut tiny).unwrap_err();
140        assert!(
141            matches!(err, Error::OutputBufferTooSmall { need, .. } if need == parsed.serialized_len()),
142            "expected OutputBufferTooSmall(need={}), got {err:?}",
143            parsed.serialized_len()
144        );
145    }
146
147    /// Descriptor with no network name bytes is valid: `[0x40, 0x00]`.
148    #[test]
149    fn empty_network_name_is_valid() {
150        let raw: &[u8] = &[TAG, 0x00];
151        let desc = NetworkNameDescriptor::parse(raw).unwrap();
152        assert!(desc.network_name.raw().is_empty());
153    }
154
155    /// `serialized_len() - 2` must equal `network_name.len()` cast to u8.
156    #[test]
157    fn descriptor_length_getter_matches_payload() {
158        let raw: Vec<u8> = vec![TAG, 0x07, b'F', b'R', b'A', b'N', b'C', b'E', b'2'];
159        let desc = NetworkNameDescriptor::parse(&raw).unwrap();
160        assert_eq!(
161            desc.serialized_len() - 2,
162            desc.network_name.raw().len() as usize
163        );
164    }
165}