dvb_subtitle/segments/
stuffing.rs1use crate::error::{Error, Result};
7use broadcast_common::{Parse, Serialize};
8
9pub const SEGMENT_TYPE: u8 = 0xFF;
11pub const HEADER_LEN: usize = 6;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize))]
17pub struct StuffingSegment<'a> {
18 pub page_id: u16,
20 #[cfg_attr(feature = "serde", serde(skip))]
22 pub data: &'a [u8],
23}
24
25impl<'a> Parse<'a> for StuffingSegment<'a> {
26 type Error = Error;
27
28 fn parse(bytes: &'a [u8]) -> Result<Self> {
29 if bytes.len() < HEADER_LEN {
30 return Err(Error::BufferTooShort {
31 need: HEADER_LEN,
32 have: bytes.len(),
33 what: "stuffing_segment",
34 });
35 }
36 if bytes[0] != crate::pes_data_field::SYNC_BYTE {
37 return Err(Error::BadSyncByte(bytes[0]));
38 }
39 if bytes[1] != SEGMENT_TYPE {
40 return Err(Error::UnknownSegmentType(bytes[1]));
41 }
42 let page_id = u16::from_be_bytes([bytes[2], bytes[3]]);
43 let segment_length = u16::from_be_bytes([bytes[4], bytes[5]]) as usize;
44 let total = HEADER_LEN + segment_length;
45 if bytes.len() < total {
46 return Err(Error::BufferTooShort {
47 need: total,
48 have: bytes.len(),
49 what: "stuffing_segment data",
50 });
51 }
52 Ok(StuffingSegment {
53 page_id,
54 data: &bytes[HEADER_LEN..total],
55 })
56 }
57}
58
59impl Serialize for StuffingSegment<'_> {
60 type Error = Error;
61
62 fn serialized_len(&self) -> usize {
63 HEADER_LEN + self.data.len()
64 }
65
66 fn serialize_into(&self, buf: &mut [u8]) -> core::result::Result<usize, Self::Error> {
67 let len = self.serialized_len();
68 if buf.len() < len {
69 return Err(Error::BufferTooShort {
70 need: len,
71 have: buf.len(),
72 what: "stuffing_segment serialize",
73 });
74 }
75 buf[0] = 0x0F;
76 buf[1] = SEGMENT_TYPE;
77 buf[2..4].copy_from_slice(&self.page_id.to_be_bytes());
78 let seg_len = crate::segments::check_segment_length(self.data.len())?;
79 buf[4..6].copy_from_slice(&seg_len.to_be_bytes());
80 buf[6..len].copy_from_slice(self.data);
81 Ok(len)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use broadcast_common::{Parse, Serialize};
89
90 #[test]
91 fn round_trip() {
92 let bytes = [0x0F, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xAA, 0xBB, 0xCC];
93 let seg = StuffingSegment::parse(&bytes).unwrap();
94 assert_eq!(seg.data, &[0xAA, 0xBB, 0xCC]);
95 let out = seg.try_to_bytes().unwrap();
96 assert_eq!(out, bytes);
97
98 let mut seg2 = seg.clone();
100 seg2.page_id = 9;
101 let out2 = seg2.try_to_bytes().unwrap();
102 assert_ne!(out2, bytes);
103 let reparse = StuffingSegment::parse(&out2).unwrap();
104 assert_eq!(reparse.page_id, 9);
105 }
106
107 #[test]
109 fn rejects_bad_sync_byte() {
110 let bytes = [0x00, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xAA, 0xBB, 0xCC];
111 assert!(matches!(
112 StuffingSegment::parse(&bytes),
113 Err(Error::BadSyncByte(0x00))
114 ));
115 }
116}