1use std::borrow::Borrow;
2use std::panic::Location;
3
4use super::endian::{BigEndian, EndianAgnostic, LittleEndian, NativeEndian};
5use super::Reader;
6use crate::Result;
7
8pub trait Parser: Reader {
10 #[track_caller]
12 #[inline]
13 fn u8(&mut self) -> Result<u8> {
14 let mut buffer = [0u8; 1];
15 self.read_into_tracked(&mut buffer, Location::caller())?;
16 Ok(buffer[0])
17 }
18
19 fn eu16<E: EndianAgnostic>(&mut self, caller: &'static Location) -> Result<u16> {
21 let mut buffer = [0u8; 2];
22 self.read_into_tracked(&mut buffer, caller)?;
23 Ok(E::u16_from_bytes(&buffer))
24 }
25
26 fn eu32<E: EndianAgnostic>(&mut self, caller: &'static Location) -> Result<u32> {
28 let mut buffer = [0u8; 4];
29 self.read_into_tracked(&mut buffer, caller)?;
30 Ok(E::u32_from_bytes(&buffer))
31 }
32
33 #[track_caller]
35 #[inline]
36 fn u16(&mut self) -> Result<u16> {
37 self.eu16::<NativeEndian>(Location::caller())
38 }
39
40 #[track_caller]
42 #[inline]
43 fn u32(&mut self) -> Result<u32> {
44 self.eu32::<NativeEndian>(Location::caller())
45 }
46
47 #[track_caller]
49 #[inline]
50 fn bu16(&mut self) -> Result<u16> {
51 self.eu16::<BigEndian>(Location::caller())
52 }
53
54 #[track_caller]
56 #[inline]
57 fn bu32(&mut self) -> Result<u32> {
58 self.eu32::<BigEndian>(Location::caller())
59 }
60
61 #[track_caller]
63 #[inline]
64 fn lu16(&mut self) -> Result<u16> {
65 self.eu16::<LittleEndian>(Location::caller())
66 }
67
68 #[track_caller]
70 #[inline]
71 fn lu32(&mut self) -> Result<u32> {
72 self.eu32::<LittleEndian>(Location::caller())
73 }
74
75 #[track_caller]
78 fn str<const L: usize, E: ParseStringEncoding>(&mut self) -> Result<String> {
79 let mut buffer = [0u8; L];
80 self.read_into_tracked(&mut buffer, Location::caller())?;
81 E::parse_str(buffer)
82 }
83
84 #[track_caller]
86 #[inline]
87 fn u8_array<const L: usize>(&mut self) -> Result<[u8; L]> {
88 self.read_buffer_of_tracked::<u8, L>(Location::caller())
89 }
90
91 #[inline]
93 fn eu16_array<E: EndianAgnostic, const L: usize>(
94 &mut self,
95 caller: &'static Location,
96 ) -> Result<[u16; L]> {
97 let mut buf = self.read_buffer_of_tracked::<u16, L>(caller)?;
98 for value in buf.iter_mut().take(L) {
99 *value = E::u16_from_native(*value);
100 }
101 Ok(buf)
102 }
103
104 #[track_caller]
106 #[inline]
107 fn bu16_array<const L: usize>(&mut self) -> Result<[u16; L]> {
108 self.eu16_array::<BigEndian, L>(Location::caller())
109 }
110
111 #[track_caller]
113 #[inline]
114 fn lu16_array<const L: usize>(&mut self) -> Result<[u16; L]> {
115 self.eu16_array::<LittleEndian, L>(Location::caller())
116 }
117
118 #[inline]
120 fn eu32_array<E: EndianAgnostic, const L: usize>(
121 &mut self,
122 caller: &'static Location,
123 ) -> Result<[u32; L]> {
124 let mut buf = self.read_buffer_of_tracked::<u32, L>(caller)?;
125 for value in buf.iter_mut().take(L) {
126 *value = E::u32_from_native(*value);
127 }
128 Ok(buf)
129 }
130
131 #[track_caller]
133 #[inline]
134 fn bu32_array<const L: usize>(&mut self) -> Result<[u32; L]> {
135 self.eu32_array::<BigEndian, L>(Location::caller())
136 }
137
138 #[track_caller]
140 #[inline]
141 fn lu32_array<const L: usize>(&mut self) -> Result<[u32; L]> {
142 self.eu32_array::<LittleEndian, L>(Location::caller())
143 }
144}
145
146impl<Base: Reader> Parser for Base {}
148
149pub trait ParseStringEncoding {
150 fn parse_str<I>(data: I) -> Result<String>
151 where
152 I: IntoIterator,
153 I::Item: Borrow<u8> + Sized;
154}
155
156#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn u8() {
166 let mut data: &[u8] = &[0x01, 0x02, 0x03, 0x04];
167 assert_eq!(data.u8().unwrap(), 0x01);
168 assert_eq!(data.u8().unwrap(), 0x02);
169 assert_eq!(data.u8().unwrap(), 0x03);
170 assert_eq!(data.u8().unwrap(), 0x04);
171 }
172
173 #[test]
174 fn u16() {
175 let mut data: &[u8] = &[0x01, 0x02, 0x01, 0x02];
176 assert_eq!(data.bu16().unwrap(), 0x0102);
177 assert_eq!(data.lu16().unwrap(), 0x0201);
178 }
179
180 #[test]
181 fn u32() {
182 let mut data: &[u8] = &[0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04];
183 assert_eq!(data.bu32().unwrap(), 0x01020304);
184 assert_eq!(data.lu32().unwrap(), 0x04030201);
185 }
186
187 #[test]
188 fn u8_array() {
189 let mut data: &[u8] = &[0x01, 0x02, 0x03, 0x04];
190 assert_eq!(data.u8_array::<4>().unwrap(), [
191 0x01, 0x02, 0x03, 0x04
192 ]);
193 }
194
195 #[test]
196 fn u16_array() {
197 let mut data: &[u8] = &[0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04];
198 assert_eq!(data.bu16_array::<2>().unwrap(), [
199 0x0102, 0x0304,
200 ]);
201 assert_eq!(data.lu16_array::<2>().unwrap(), [
202 0x0201, 0x0403,
203 ]);
204 }
205
206 #[test]
207 fn u32_array() {
208 let mut data: &[u8] = &[
209 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
210 0x07, 0x08,
211 ];
212 assert_eq!(data.bu32_array::<2>().unwrap(), [
213 0x01020304, 0x05060708
214 ]);
215 assert_eq!(data.lu32_array::<2>().unwrap(), [
216 0x04030201, 0x08070605
217 ]);
218 }
219}