dvb_si/descriptors/
related_content.rs1use crate::error::{Error, Result};
11use crate::traits::Descriptor;
12use dvb_common::{Parse, Serialize};
13
14pub const TAG: u8 = 0x74;
16const HEADER_LEN: usize = 2;
17
18#[derive(Debug, Clone, PartialEq, Eq, Default)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub struct RelatedContentDescriptor;
24
25impl<'a> Parse<'a> for RelatedContentDescriptor {
26 type Error = crate::error::Error;
27 fn parse(bytes: &'a [u8]) -> Result<Self> {
28 if bytes.len() < HEADER_LEN {
29 return Err(Error::BufferTooShort {
30 need: HEADER_LEN,
31 have: bytes.len(),
32 what: "RelatedContentDescriptor header",
33 });
34 }
35 if bytes[0] != TAG {
36 return Err(Error::InvalidDescriptor {
37 tag: bytes[0],
38 reason: "unexpected tag for related_content_descriptor",
39 });
40 }
41 let length = bytes[1] as usize;
42 let end = HEADER_LEN + length;
43 if bytes.len() < end {
44 return Err(Error::BufferTooShort {
45 need: end,
46 have: bytes.len(),
47 what: "RelatedContentDescriptor body",
48 });
49 }
50 Ok(Self)
53 }
54}
55
56impl Serialize for RelatedContentDescriptor {
57 type Error = crate::error::Error;
58 fn serialized_len(&self) -> usize {
59 HEADER_LEN
60 }
61
62 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
63 let len = self.serialized_len();
64 if buf.len() < len {
65 return Err(Error::OutputBufferTooSmall {
66 need: len,
67 have: buf.len(),
68 });
69 }
70 buf[0] = TAG;
71 buf[1] = 0;
72 Ok(len)
73 }
74}
75
76impl<'a> Descriptor<'a> for RelatedContentDescriptor {
77 const TAG: u8 = TAG;
78 fn descriptor_length(&self) -> u8 {
79 0
80 }
81}
82
83impl<'a> crate::traits::DescriptorDef<'a> for RelatedContentDescriptor {
84 const TAG: u8 = TAG;
85 const NAME: &'static str = "RELATED_CONTENT";
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn parse_empty_marker() {
94 let bytes = [TAG, 0];
95 let d = RelatedContentDescriptor::parse(&bytes).unwrap();
96 assert_eq!(d, RelatedContentDescriptor);
97 }
98
99 #[test]
100 fn parse_rejects_wrong_tag() {
101 assert!(matches!(
102 RelatedContentDescriptor::parse(&[0x73, 0]).unwrap_err(),
103 Error::InvalidDescriptor { tag: 0x73, .. }
104 ));
105 }
106
107 #[test]
108 fn parse_rejects_short_header() {
109 assert!(matches!(
110 RelatedContentDescriptor::parse(&[TAG]).unwrap_err(),
111 Error::BufferTooShort { .. }
112 ));
113 }
114
115 #[test]
116 fn parse_rejects_length_overrunning_buffer() {
117 let bytes = [TAG, 3, 1, 2];
118 assert!(matches!(
119 RelatedContentDescriptor::parse(&bytes).unwrap_err(),
120 Error::BufferTooShort { .. }
121 ));
122 }
123
124 #[test]
125 fn serialize_round_trip() {
126 let d = RelatedContentDescriptor;
127 let mut buf = vec![0u8; d.serialized_len()];
128 let n = d.serialize_into(&mut buf).unwrap();
129 assert_eq!(n, 2);
130 assert_eq!(buf, vec![TAG, 0]);
131 assert_eq!(RelatedContentDescriptor::parse(&buf).unwrap(), d);
132 }
133
134 #[test]
135 fn serialize_rejects_too_small_buffer() {
136 let d = RelatedContentDescriptor;
137 let mut buf = vec![0u8; 1];
138 assert!(matches!(
139 d.serialize_into(&mut buf).unwrap_err(),
140 Error::OutputBufferTooSmall { .. }
141 ));
142 }
143
144 #[cfg(feature = "serde")]
145 #[test]
146 fn serde_round_trip() {
147 let d = RelatedContentDescriptor;
148 let j = serde_json::to_string(&d).unwrap();
149 let back: RelatedContentDescriptor = serde_json::from_str(&j).unwrap();
150 assert_eq!(back, d);
151 }
152}