va_ts/section/
pmt.rs

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
10/// ISO/IEC 13818-1
11///
12/// Program Map Table
13pub 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    /// seek
39    #[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    /// seek
54    #[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    /// buffer seeked
84    #[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    /// seek
181    #[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}