1use crate::error::{Error, Kind as ErrorKind};
2use crate::header::{Adaptation, Header};
3use crate::pcr::PCR;
4use crate::pid::PID;
5use crate::result::Result;
6
7pub struct Packet<'buf> {
8 buf: &'buf [u8],
9}
10
11impl<'buf> Packet<'buf> {
12 pub const SZ: usize = 188;
13 const SYNC_BYTE: u8 = 0x47;
14
15 #[inline(always)]
16 pub fn new(buf: &'buf [u8]) -> Result<Packet<'buf>> {
17 let pkt = Packet { buf };
18
19 pkt.validate()?;
20
21 Ok(pkt)
22 }
23
24 #[inline(always)]
25 fn validate(&self) -> Result<()> {
26 if self.buf.len() != Self::SZ {
27 Err(Error::new(ErrorKind::Buf(self.buf.len(), Self::SZ)))
28 } else if self.buf[0] != Self::SYNC_BYTE {
29 Err(Error::new(ErrorKind::SyncByte(self.buf[0])))
30 } else {
31 Ok(())
32 }
33 }
34
35 #[inline(always)]
37 fn buf_pos_adaptation() -> usize {
38 Header::SZ
39 }
40
41 #[inline(always)]
45 fn buf_pos_payload(&self, is_section: bool) -> usize {
46 let mut pos = Self::buf_pos_adaptation();
47 let header = self.header();
48
49 if header.got_adaptation() {
50 let adapt = Adaptation::new(self.buf_seek(pos));
53 pos += adapt.sz();
54 }
55
56 if header.pusi() && is_section {
57 pos += (self.buf[pos] as usize) + 1;
70 }
71
72 pos
73 }
74
75 #[inline(always)]
76 fn buf_seek(&self, offset: usize) -> &'buf [u8] {
77 &self.buf[offset..]
78 }
79
80 #[inline(always)]
81 fn buf_try_seek(&self, offset: usize) -> Result<&'buf [u8]> {
82 if self.buf.len() <= offset {
83 Err(Error::new(ErrorKind::Buf(self.buf.len(), Self::SZ)))
84 } else {
85 Ok(self.buf_seek(offset))
86 }
87 }
88
89 #[inline(always)]
90 fn buf_adaptation(&self) -> Result<&'buf [u8]> {
91 self.buf_try_seek(Self::buf_pos_adaptation())
92 }
93
94 #[inline(always)]
95 fn buf_payload(&self, is_section: bool) -> Result<&'buf [u8]> {
96 self.buf_try_seek(self.buf_pos_payload(is_section))
97 }
98
99 #[inline(always)]
100 pub fn buf_payload_section(&self) -> Result<&'buf [u8]> {
101 self.buf_payload(true)
102 }
103
104 #[inline(always)]
105 pub fn buf_payload_pes(&self) -> Result<&'buf [u8]> {
106 self.buf_payload(false)
107 }
108
109 #[inline(always)]
111 fn header(&self) -> Header<'buf> {
112 Header::new(self.buf)
113 }
114
115 #[inline(always)]
116 fn adaptation(&self) -> Option<Result<Adaptation<'buf>>> {
117 let header = self.header();
118
119 if header.got_adaptation() {
120 match self.buf_adaptation() {
122 Ok(buf) => Some(Adaptation::try_new(buf)),
123 Err(e) => Some(Err(e)),
124 }
125 } else {
126 None
127 }
128 }
129
130 #[inline(always)]
131 pub fn pid(&self) -> PID {
132 self.header().pid()
133 }
134
135 #[inline(always)]
136 pub fn cc(&self) -> u8 {
137 self.header().cc()
138 }
139
140 #[inline(always)]
141 pub fn pusi(&self) -> bool {
142 self.header().pusi()
143 }
144
145 #[inline(always)]
146 pub fn pcr(&self) -> Result<Option<PCR<'buf>>> {
147 self.adaptation()
148 .and_then(|res| match res {
149 Ok(adapt) => adapt.pcr().map(Ok),
150 Err(e) => Some(Err(e)),
151 })
152 .transpose()
153 }
154
155 #[inline(always)]
157 pub fn pat(&self) -> Result<Option<&'buf [u8]>> {
158 let header = self.header();
159
160 if !header.got_payload() {
161 return Ok(None);
162 }
163
164 let res = if self.pid() == PID::PAT {
165 match self.buf_payload_section() {
167 Ok(buf) => Some(Ok(buf)),
168 Err(e) => Some(Err(e)),
169 }
170 } else {
171 None
172 };
173
174 res.transpose()
175 }
176
177 #[inline(always)]
179 pub fn pmt(&self, pid: u16) -> Result<Option<&'buf [u8]>> {
180 let header = self.header();
181
182 if !header.got_payload() {
183 return Ok(None);
184 }
185
186 let res = if u16::from(self.pid()) == pid {
187 match self.buf_payload_section() {
189 Ok(buf) => Some(Ok(buf)),
190 Err(e) => Some(Err(e)),
191 }
192 } else {
193 None
194 };
195
196 res.transpose()
197 }
198
199 #[inline(always)]
201 pub fn eit(&self) -> Result<Option<&'buf [u8]>> {
202 let header = self.header();
203
204 if !header.got_payload() {
205 return Ok(None);
206 }
207
208 let res = if self.pid() == PID::EIT {
209 match self.buf_payload_section() {
211 Ok(buf) => Some(Ok(buf)),
212 Err(e) => Some(Err(e)),
213 }
214 } else {
215 None
216 };
217
218 res.transpose()
219 }
220}