va_ts/section/
traits.rs

1use std::marker::PhantomData;
2
3use crate::result::Result;
4use crate::table_id::TableID;
5
6pub trait Bufer<'buf> {
7    /// borrow a reference to the underlying buffer
8    fn buf(&self) -> &'buf [u8];
9}
10
11pub const HEADER_SZ: usize = 3;
12#[allow(dead_code)]
13pub const HEADER_MAX_SECTION_LENGTH: usize = 0x3FD; // 1021
14
15pub trait WithHeader<'buf>: Bufer<'buf> {
16    /// buffer seeked
17    #[inline(always)]
18    fn b(&self) -> &'buf [u8] {
19        self.buf()
20    }
21
22    #[inline(always)]
23    fn table_id(&self) -> TableID {
24        TableID::from(self.b()[0])
25    }
26
27    /// if set to 1 (true) - 4th and 5th bytes
28    /// are table-id-extension
29    ///
30    /// must be set to 1 for:
31    /// PAT, CAT, PMT
32    /// NIT, EIT, BAT, SDT
33    #[inline(always)]
34    fn section_syntax_indicator(&self) -> bool {
35        (self.b()[1] & 0b1000_0000) != 0
36    }
37
38    #[inline(always)]
39    fn section_length(&self) -> u16 {
40        (u16::from(self.b()[1] & 0b0000_1111) << 8) | u16::from(self.b()[2])
41    }
42
43    /// complete section length
44    #[inline(always)]
45    fn sz(&self) -> usize {
46        HEADER_SZ + usize::from(self.section_length())
47    }
48}
49
50pub trait WithTableIDExtension<'buf>: Bufer<'buf> {
51    /// buffer seeked
52    #[inline(always)]
53    fn b(&self) -> &'buf [u8] {
54        self.buf()
55    }
56
57    #[inline(always)]
58    fn table_id_extension(&self) -> u16 {
59        (u16::from(self.b()[3]) << 8) | u16::from(self.b()[4])
60    }
61}
62
63pub const SYNTAX_SECTION_SZ: usize = 5;
64
65pub trait WithSyntaxSection<'buf>: Bufer<'buf> {
66    /// buffer seeked
67    #[inline(always)]
68    fn b(&self) -> &'buf [u8] {
69        &self.buf()[HEADER_SZ..]
70    }
71
72    #[inline(always)]
73    #[allow(dead_code)]
74    fn version_number(&self) -> u8 {
75        (self.b()[2] & 0b0011_1110) >> 1
76    }
77
78    #[inline(always)]
79    fn current_next_indicator(&self) -> bool {
80        (self.b()[2] & 0b0000_0001) != 0
81    }
82
83    #[inline(always)]
84    fn section_number(&self) -> u8 {
85        self.b()[3]
86    }
87
88    #[inline(always)]
89    fn last_section_number(&self) -> u8 {
90        self.b()[4]
91    }
92}
93
94pub trait Szer {
95    fn sz(&self) -> usize;
96}
97
98pub trait TryNewer<'buf> {
99    fn try_new(buf: &'buf [u8]) -> Result<Self>
100    where
101        Self: Sized;
102}
103
104pub struct Cursor<'buf, T> {
105    buf: &'buf [u8],
106    phantom: PhantomData<T>,
107}
108
109impl<'buf, T> Cursor<'buf, T> {
110    #[inline(always)]
111    pub fn new(buf: &'buf [u8]) -> Cursor<'buf, T> {
112        Cursor {
113            buf,
114            phantom: PhantomData,
115        }
116    }
117
118    #[inline(always)]
119    fn buf_drain(&mut self) {
120        self.buf = &self.buf[self.buf.len()..];
121    }
122}
123
124impl<'buf, T> Iterator for Cursor<'buf, T>
125where
126    T: TryNewer<'buf> + Szer,
127{
128    type Item = Result<T>;
129
130    fn next(&mut self) -> Option<Self::Item> {
131        if self.buf.is_empty() {
132            return None;
133        }
134
135        let row = match T::try_new(self.buf) {
136            Ok(row) => row,
137            Err(e) => {
138                self.buf_drain();
139                return Some(Err(e));
140            }
141        };
142
143        // seek buf
144        if self.buf.len() > row.sz() {
145            self.buf = &self.buf[row.sz()..];
146        } else {
147            self.buf_drain();
148        }
149
150        Some(Ok(row))
151    }
152}
153
154pub const CRC32_SZ: usize = 4;
155
156pub(crate) trait WithCRC32<'buf>: Bufer<'buf> {}