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