1use std::fmt;
2
3use crate::descriptor::Descriptor;
4use crate::result::Result;
5use crate::subtable_id::{SubtableID, SubtableIDer};
6
7use super::traits::*;
8
9pub struct SDT<'buf> {
13 buf: &'buf [u8],
14}
15
16impl<'buf> SDT<'buf> {
17 const HEADER_SPECIFIC_SZ: usize = 3;
18 const HEADER_FULL_SZ: usize = HEADER_SZ + SYNTAX_SECTION_SZ + Self::HEADER_SPECIFIC_SZ;
19
20 #[inline(always)]
21 pub fn new(buf: &'buf [u8]) -> SDT<'buf> {
22 SDT { buf }
23 }
24
25 #[inline(always)]
26 pub fn try_new(buf: &'buf [u8]) -> Result<SDT<'buf>> {
27 let s = Self::new(buf);
28 s.validate()?;
29 Ok(s)
30 }
31
32 #[inline(always)]
33 pub fn validate(&self) -> Result<()> {
34 Ok(())
35 }
36
37 #[inline(always)]
39 fn buf_streams(&self) -> &'buf [u8] {
40 let lft = Self::HEADER_FULL_SZ;
41 let mut rght = HEADER_SZ + (self.section_length() as usize);
42
43 if rght >= self.buf.len() {
44 rght = self.buf.len();
45 }
46
47 rght -= CRC32_SZ;
48
49 &self.buf[lft..rght]
50 }
51
52 #[inline(always)]
53 pub fn streams(&self) -> Cursor<'buf, Stream> {
54 Cursor::new(self.buf_streams())
55 }
56
57 #[inline(always)]
58 pub fn transport_stream_id(&self) -> u16 {
59 self.table_id_extension()
60 }
61}
62
63trait WithSDTHeaderSpecific<'buf>: Bufer<'buf> {
64 #[inline(always)]
66 fn b(&self) -> &'buf [u8] {
67 &self.buf()[HEADER_SZ + SYNTAX_SECTION_SZ..]
68 }
69
70 #[inline(always)]
71 fn original_network_id(&self) -> u16 {
72 u16::from(self.b()[0]) | u16::from(self.b()[1])
73 }
74}
75
76impl<'buf> Bufer<'buf> for SDT<'buf> {
77 fn buf(&self) -> &'buf [u8] {
78 self.buf
79 }
80}
81
82impl<'buf> WithHeader<'buf> for SDT<'buf> {}
83impl<'buf> WithTableIDExtension<'buf> for SDT<'buf> {}
84impl<'buf> WithSyntaxSection<'buf> for SDT<'buf> {}
85impl<'buf> WithSDTHeaderSpecific<'buf> for SDT<'buf> {}
86impl<'buf> WithCRC32<'buf> for SDT<'buf> {}
87
88impl<'buf> fmt::Debug for SDT<'buf> {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 write!(
91 f,
92 ":SDT (:id {:?} :transport-stream-id {} :section-length {} :section {}/{})",
93 self.subtable_id(),
94 self.transport_stream_id(),
95 self.section_length(),
96 self.section_number(),
97 self.last_section_number(),
98 )?;
99
100 write!(f, "\n :streams")?;
101 for p in self.streams().filter_map(Result::ok) {
102 write!(f, "\n ")?;
103 p.fmt(f)?;
104 }
105
106 Ok(())
107 }
108}
109
110impl<'buf> SubtableIDer for SDT<'buf> {
111 #[inline(always)]
112 fn subtable_id(&self) -> SubtableID {
113 SubtableID::SDT(
114 self.table_id(),
115 self.transport_stream_id(),
116 self.original_network_id(),
117 self.version_number(),
118 )
119 }
120}
121
122pub struct Stream<'buf> {
123 buf: &'buf [u8],
124}
125
126impl<'buf> Stream<'buf> {
127 const HEADER_SZ: usize = 5;
128
129 #[inline(always)]
130 pub fn new(buf: &'buf [u8]) -> Stream<'buf> {
131 Stream { buf }
132 }
133
134 #[inline(always)]
135 pub fn service_id(&self) -> u16 {
136 u16::from(self.buf[0]) | u16::from(self.buf[1])
137 }
138
139 #[inline(always)]
140 pub fn eit_schedule_flag(&self) -> bool {
141 ((self.buf[2] & 0b0000_0010) >> 1) != 0
142 }
143
144 #[inline(always)]
145 pub fn eit_present_following_flag(&self) -> bool {
146 (self.buf[2] & 0b0000_0001) != 0
147 }
148
149 #[inline(always)]
151 pub fn running_status(&self) -> u8 {
152 (self.buf[3] & 0b1110_0000) >> 5
153 }
154
155 #[inline(always)]
156 pub fn free_ca_mode(&self) -> bool {
157 (self.buf[3] & 0b0001_0000) != 0
158 }
159
160 #[inline(always)]
161 pub fn descriptors_loop_length(&self) -> u16 {
162 (u16::from(self.buf[3] & 0b0000_1111) << 8) | u16::from(self.buf[4])
163 }
164
165 #[inline(always)]
167 fn buf_descriptors(&self) -> &'buf [u8] {
168 let lft = Self::HEADER_SZ;
169 let mut rght = lft + (self.descriptors_loop_length() as usize);
170
171 if rght >= self.buf.len() {
172 rght = self.buf.len();
173 }
174
175 &self.buf[lft..rght]
176 }
177
178 #[inline(always)]
179 pub fn descriptors(&self) -> Option<Cursor<'buf, Descriptor>> {
180 if self.descriptors_loop_length() != 0 {
181 Some(Cursor::new(self.buf_descriptors()))
182 } else {
183 None
184 }
185 }
186}
187
188impl<'buf> Szer for Stream<'buf> {
189 #[inline(always)]
190 fn sz(&self) -> usize {
191 Self::HEADER_SZ + (self.descriptors_loop_length() as usize)
192 }
193}
194
195impl<'buf> TryNewer<'buf> for Stream<'buf> {
196 #[inline(always)]
197 fn try_new(buf: &'buf [u8]) -> Result<Stream<'buf>> {
198 let s = Stream::new(buf);
199 Ok(s)
200 }
201}
202
203impl<'buf> fmt::Debug for Stream<'buf> {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 write!(
206 f,
207 ":stream (:service-id {:?} :running-status {:?})",
208 self.service_id(),
209 self.running_status(),
210 )?;
211
212 write!(f, "\n :descriptors")?;
213 match self.descriptors() {
214 Some(descs) => {
215 for d in descs.filter_map(Result::ok) {
216 write!(f, "\n ")?;
217 d.fmt(f)?;
218 }
219 }
220 None => write!(f, " ~")?,
221 }
222
223 Ok(())
224 }
225}