dvb_si/descriptors/
flex_mux_timing.rs1use super::descriptor_body;
7use crate::error::{Error, Result};
8use dvb_common::{Parse, Serialize};
9
10pub const TAG: u8 = 0x2C;
12const HEADER_LEN: usize = 2;
13const BODY_LEN: u8 = 10;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18pub struct FlexMuxTimingDescriptor {
19 pub fcr_es_id: u16,
21 pub fcr_resolution: u32,
23 pub fcr_length: u8,
25 pub fmx_rate_length: u8,
27}
28
29impl<'a> Parse<'a> for FlexMuxTimingDescriptor {
30 type Error = crate::error::Error;
31
32 fn parse(bytes: &'a [u8]) -> Result<Self> {
33 let body = descriptor_body(
34 bytes,
35 TAG,
36 "FlexMuxTimingDescriptor",
37 "unexpected tag for FlexMuxTiming_descriptor",
38 )?;
39 if body.len() != BODY_LEN as usize {
40 return Err(Error::InvalidDescriptor {
41 tag: TAG,
42 reason: "FlexMuxTiming_descriptor length must equal 10",
43 });
44 }
45 Ok(Self {
46 fcr_es_id: u16::from_be_bytes([body[0], body[1]]),
47 fcr_resolution: u32::from_be_bytes([body[2], body[3], body[4], body[5]]),
48 fcr_length: body[6],
49 fmx_rate_length: body[7],
50 })
51 }
52}
53
54impl Serialize for FlexMuxTimingDescriptor {
55 type Error = crate::error::Error;
56
57 fn serialized_len(&self) -> usize {
58 HEADER_LEN + BODY_LEN as usize
59 }
60
61 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
62 let len = self.serialized_len();
63 if buf.len() < len {
64 return Err(Error::OutputBufferTooSmall {
65 need: len,
66 have: buf.len(),
67 });
68 }
69 buf[0] = TAG;
70 buf[1] = BODY_LEN;
71 buf[HEADER_LEN..HEADER_LEN + 2].copy_from_slice(&self.fcr_es_id.to_be_bytes());
72 buf[HEADER_LEN + 2..HEADER_LEN + 6].copy_from_slice(&self.fcr_resolution.to_be_bytes());
73 buf[HEADER_LEN + 6] = self.fcr_length;
74 buf[HEADER_LEN + 7] = self.fmx_rate_length;
75 Ok(len)
76 }
77}
78impl<'a> crate::traits::DescriptorDef<'a> for FlexMuxTimingDescriptor {
79 const TAG: u8 = TAG;
80 const NAME: &'static str = "FLEX_MUX_TIMING";
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn parse_extracts_fields() {
89 let bytes = [
90 TAG, 10, 0x00, 0x01, 0x12, 0x34, 0x56, 0x78, 0x05, 0x1E, 0, 0,
91 ];
92 let d = FlexMuxTimingDescriptor::parse(&bytes).unwrap();
93 assert_eq!(d.fcr_es_id, 0x0001);
94 assert_eq!(d.fcr_resolution, 0x12345678);
95 assert_eq!(d.fcr_length, 0x05);
96 assert_eq!(d.fmx_rate_length, 0x1E);
97 }
98
99 #[test]
100 fn parse_rejects_wrong_tag() {
101 let err =
102 FlexMuxTimingDescriptor::parse(&[0x02, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap_err();
103 assert!(matches!(err, Error::InvalidDescriptor { tag: 0x02, .. }));
104 }
105
106 #[test]
107 fn parse_rejects_wrong_length() {
108 let err = FlexMuxTimingDescriptor::parse(&[TAG, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0]).unwrap_err();
109 assert!(matches!(err, Error::InvalidDescriptor { .. }));
110 }
111
112 #[test]
113 fn parse_rejects_short_buffer() {
114 let err = FlexMuxTimingDescriptor::parse(&[TAG, 11, 0, 0]).unwrap_err();
115 assert!(matches!(err, Error::BufferTooShort { .. }));
116 }
117
118 #[test]
119 fn serialize_round_trip() {
120 let d = FlexMuxTimingDescriptor {
121 fcr_es_id: 0xBEEF,
122 fcr_resolution: 0xDEADBEEF,
123 fcr_length: 0x42,
124 fmx_rate_length: 0x99,
125 };
126 let mut buf = vec![0u8; d.serialized_len()];
127 d.serialize_into(&mut buf).unwrap();
128 let reparsed = FlexMuxTimingDescriptor::parse(&buf).unwrap();
129 assert_eq!(d, reparsed);
130 }
131
132 #[test]
133 fn serialize_rejects_small_buffer() {
134 let d = FlexMuxTimingDescriptor {
135 fcr_es_id: 0,
136 fcr_resolution: 0,
137 fcr_length: 0,
138 fmx_rate_length: 0,
139 };
140 let mut tiny = vec![0u8; 5];
141 let err = d.serialize_into(&mut tiny).unwrap_err();
142 assert!(matches!(err, Error::OutputBufferTooSmall { .. }));
143 }
144}