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