Skip to main content

dvb_si/descriptors/
stream_identifier.rs

1//! Stream Identifier Descriptor — ETSI EN 300 468 §6.2.41 (tag 0x52).
2//!
3//! One-byte `component_tag` that anchors components named elsewhere (e.g. by
4//! component_descriptor).
5
6use super::descriptor_body;
7use crate::error::{Error, Result};
8use dvb_common::{Parse, Serialize};
9
10/// Descriptor tag for stream_identifier_descriptor.
11pub const TAG: u8 = 0x52;
12const HEADER_LEN: usize = 2;
13const BODY_LEN: u8 = 1;
14
15/// Stream Identifier Descriptor.
16#[derive(Debug, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18pub struct StreamIdentifierDescriptor {
19    /// Component tag used to cross-reference a component_descriptor.
20    pub component_tag: u8,
21}
22
23impl<'a> Parse<'a> for StreamIdentifierDescriptor {
24    type Error = crate::error::Error;
25    fn parse(bytes: &'a [u8]) -> Result<Self> {
26        let body = descriptor_body(
27            bytes,
28            TAG,
29            "StreamIdentifierDescriptor",
30            "unexpected tag for stream_identifier_descriptor",
31        )?;
32        if body.len() != BODY_LEN as usize {
33            return Err(Error::InvalidDescriptor {
34                tag: TAG,
35                reason: "stream_identifier_descriptor length must equal 1",
36            });
37        }
38        Ok(Self {
39            component_tag: body[0],
40        })
41    }
42}
43
44impl Serialize for StreamIdentifierDescriptor {
45    type Error = crate::error::Error;
46    fn serialized_len(&self) -> usize {
47        HEADER_LEN + BODY_LEN as usize
48    }
49
50    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
51        let len = self.serialized_len();
52        if buf.len() < len {
53            return Err(Error::OutputBufferTooSmall {
54                need: len,
55                have: buf.len(),
56            });
57        }
58        buf[0] = TAG;
59        buf[1] = BODY_LEN;
60        buf[2] = self.component_tag;
61        Ok(len)
62    }
63}
64impl<'a> crate::traits::DescriptorDef<'a> for StreamIdentifierDescriptor {
65    const TAG: u8 = TAG;
66    const NAME: &'static str = "STREAM_IDENTIFIER";
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn parse_extracts_component_tag() {
75        let d = StreamIdentifierDescriptor::parse(&[TAG, 1, 0x42]).unwrap();
76        assert_eq!(d.component_tag, 0x42);
77    }
78
79    #[test]
80    fn parse_rejects_wrong_tag() {
81        let err = StreamIdentifierDescriptor::parse(&[0x53, 1, 0]).unwrap_err();
82        assert!(matches!(err, Error::InvalidDescriptor { tag: 0x53, .. }));
83    }
84
85    #[test]
86    fn parse_rejects_wrong_length() {
87        let err = StreamIdentifierDescriptor::parse(&[TAG, 2, 0, 0]).unwrap_err();
88        assert!(matches!(err, Error::InvalidDescriptor { .. }));
89    }
90
91    #[test]
92    fn parse_rejects_short_buffer() {
93        let err = StreamIdentifierDescriptor::parse(&[TAG]).unwrap_err();
94        assert!(matches!(err, Error::BufferTooShort { .. }));
95    }
96
97    #[test]
98    fn serialize_round_trip() {
99        let d = StreamIdentifierDescriptor {
100            component_tag: 0xFE,
101        };
102        let mut buf = vec![0u8; d.serialized_len()];
103        d.serialize_into(&mut buf).unwrap();
104        assert_eq!(StreamIdentifierDescriptor::parse(&buf).unwrap(), d);
105    }
106}