1use std::marker::PhantomData;
2
3use crate::result::Result;
4use crate::table_id::TableID;
5
6pub trait Bufer<'buf> {
7 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; pub trait WithHeader<'buf>: Bufer<'buf> {
16 #[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 #[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 #[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 #[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 #[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 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> {}