1use std::fmt::Debug;
6use std::io::{Cursor, Seek as _, SeekFrom};
7use std::ops::Deref;
8use zerocopy::{FromBytes, Immutable, KnownLayout, Ref, SplitByteSlice, Unaligned};
9
10trait ParseCursor: Sized {
12 type Inner;
14
15 type Error;
17
18 fn remaining_slice(&self) -> &[u8];
20
21 fn len(&self) -> usize;
23
24 fn seek_forward(&mut self, num_bytes: usize) -> Result<(), Self::Error>;
26
27 #[allow(dead_code)]
29 fn into_inner(self) -> Self::Inner;
30}
31
32impl<T: AsRef<[u8]>> ParseCursor for Cursor<T> {
33 type Inner = T;
34 type Error = std::io::Error;
35
36 fn remaining_slice(&self) -> &[u8] {
37 let s: &[u8] = self.get_ref().as_ref();
38 let p = self.position() as usize;
39 &s[p..]
40 }
41
42 fn len(&self) -> usize {
43 let position = self.position() as usize;
44 self.get_ref().as_ref().len() - position
45 }
46
47 fn seek_forward(&mut self, num_bytes: usize) -> Result<(), Self::Error> {
48 self.seek(SeekFrom::Current(num_bytes as i64)).map(|_| ())
49 }
50
51 #[allow(dead_code)]
52 fn into_inner(self) -> Self::Inner {
53 self.into_inner()
54 }
55}
56
57pub trait ParseStrategy: Debug + PartialEq + Sized {
70 type Input;
72
73 type Output<T: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>: Debug
75 + PartialEq;
76
77 type Slice<T: Debug + FromBytes + Immutable + PartialEq + Unaligned>: Debug + PartialEq;
79
80 fn parse<T: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
84 self,
85 ) -> Option<(Self::Output<T>, Self)>;
86
87 fn parse_slice<T: Clone + Debug + FromBytes + Immutable + PartialEq + Unaligned>(
91 self,
92 count: usize,
93 ) -> Option<(Self::Slice<T>, Self)>;
94
95 fn deref<'a, T: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
97 output: &'a Self::Output<T>,
98 ) -> &'a T;
99
100 fn deref_slice<'a, T: Debug + FromBytes + Immutable + PartialEq + Unaligned>(
102 slice: &'a Self::Slice<T>,
103 ) -> &'a [T];
104
105 fn len(&self) -> usize;
107
108 fn into_inner(self) -> Self::Input;
110}
111
112#[derive(Clone, Debug, PartialEq)]
134pub struct ByRef<B: SplitByteSlice> {
135 input: B,
136 tail: B,
137}
138
139impl<B: SplitByteSlice + Clone> ByRef<B> {
140 pub fn new(byte_slice: B) -> Self {
142 Self { input: byte_slice.clone(), tail: byte_slice }
143 }
144}
145
146impl<B: Debug + SplitByteSlice + PartialEq> ParseStrategy for ByRef<B> {
147 type Input = B;
148 type Output<T: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned> = Ref<B, T>;
149 type Slice<T: Debug + FromBytes + Immutable + PartialEq + Unaligned> = Ref<B, [T]>;
150
151 fn parse<T: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
154 self,
155 ) -> Option<(Self::Output<T>, Self)> {
156 let (output, tail) = Ref::from_prefix(self.tail).ok()?;
157 Some((output, Self { input: self.input, tail }))
158 }
159
160 fn parse_slice<T: Clone + Debug + FromBytes + Immutable + PartialEq + Unaligned>(
163 self,
164 num: usize,
165 ) -> Option<(Self::Slice<T>, Self)> {
166 let (slice, tail) = Ref::from_prefix_with_elems(self.tail, num).ok()?;
167 Some((slice, Self { input: self.input, tail }))
168 }
169
170 fn deref<'a, T: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
171 output: &'a Self::Output<T>,
172 ) -> &'a T {
173 output.deref() as &T
174 }
175
176 fn deref_slice<'a, T: Debug + FromBytes + Immutable + PartialEq + Unaligned>(
177 slice: &'a Self::Slice<T>,
178 ) -> &'a [T] {
179 slice.deref() as &[T]
180 }
181
182 fn len(&self) -> usize {
183 self.tail.len()
184 }
185
186 fn into_inner(self) -> Self::Input {
187 self.input
188 }
189}
190
191#[derive(Clone, Debug, PartialEq)]
209pub struct ByValue<T: AsRef<[u8]>>(Cursor<T>);
210
211impl<T: AsRef<[u8]>> ByValue<T> {
212 pub fn new(data: T) -> Self {
214 Self(Cursor::new(data))
215 }
216}
217
218impl<T: AsRef<[u8]> + Debug + PartialEq> ParseStrategy for ByValue<T>
219where
220 Cursor<T>: Debug + ParseCursor + PartialEq,
221{
222 type Input = T;
223 type Output<O: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned> = O;
224 type Slice<S: Debug + FromBytes + Immutable + PartialEq + Unaligned> = Vec<S>;
225
226 fn parse<P: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
228 mut self,
229 ) -> Option<(Self::Output<P>, Self)> {
230 let (output, _) = P::read_from_prefix(ParseCursor::remaining_slice(&self.0)).ok()?;
231 if self.0.seek_forward(std::mem::size_of_val(&output)).is_err() {
232 return None;
233 }
234 Some((output, self))
235 }
236
237 fn parse_slice<PS: Clone + Debug + FromBytes + Immutable + PartialEq + Unaligned>(
240 mut self,
241 count: usize,
242 ) -> Option<(Self::Slice<PS>, Self)> {
243 let (slice, _) =
244 <[PS]>::ref_from_prefix_with_elems(ParseCursor::remaining_slice(&self.0), count)
245 .ok()?;
246 let size = std::mem::size_of_val(&slice);
247 let slice = slice.to_owned();
248 if self.0.seek_forward(size).is_err() {
249 return None;
250 }
251 Some((slice, self))
252 }
253
254 fn deref<'a, D: Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
255 output: &'a Self::Output<D>,
256 ) -> &'a D {
257 output
258 }
259
260 fn deref_slice<'a, DS: Debug + FromBytes + Immutable + PartialEq + Unaligned>(
261 slice: &'a Self::Slice<DS>,
262 ) -> &'a [DS] {
263 slice
264 }
265
266 fn len(&self) -> usize {
267 self.0.len()
268 }
269
270 fn into_inner(self) -> Self::Input {
271 self.0.into_inner()
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use super::*;
278 use zerocopy::little_endian as le;
279
280 #[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
281 #[repr(C, packed)]
282 struct SomeNumbers {
283 a: u8,
284 b: le::U32,
285 c: le::U16,
286 d: u8,
287 }
288
289 fn do_by_value<
291 D: AsRef<[u8]> + Debug + PartialEq,
292 T: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned,
293 >(
294 data: D,
295 ) -> (T, ByValue<D>) {
296 let parser = ByValue::new(data);
297 parser.parse::<T>().expect("some numbers")
298 }
299 fn do_slice_by_value<
300 D: AsRef<[u8]> + Debug + PartialEq,
301 T: Clone + Debug + FromBytes + Immutable + PartialEq + Unaligned,
302 >(
303 data: D,
304 count: usize,
305 ) -> (Vec<T>, ByValue<D>) {
306 let parser = ByValue::new(data);
307 parser.parse_slice::<T>(count).expect("some numbers")
308 }
309
310 #[test]
311 fn by_ref_slice_u8_parse() {
312 let bytes: Vec<u8> = (0..8).collect();
313 let parser = ByRef::new(bytes.as_slice());
314 let (some_numbers, parser) = parser.parse::<SomeNumbers>().expect("some numbers");
315 assert_eq!(0, some_numbers.a);
316 assert_eq!(7, some_numbers.d);
317 assert_eq!(0, parser.tail.len());
318 }
319
320 #[test]
321 fn by_ref_slice_u8_parse_slice() {
322 let bytes: Vec<u8> = (0..24).collect();
323 let parser = ByRef::new(bytes.as_slice());
324 let (some_numbers, parser) = parser.parse_slice::<SomeNumbers>(3).expect("some numbers");
325 assert_eq!(3, some_numbers.len());
326 assert_eq!(0, some_numbers[0].a);
327 assert_eq!(7, some_numbers[0].d);
328 assert_eq!(8, some_numbers[1].a);
329 assert_eq!(15, some_numbers[1].d);
330 assert_eq!(16, some_numbers[2].a);
331 assert_eq!(23, some_numbers[2].d);
332 assert_eq!(0, parser.tail.len());
333 }
334
335 #[test]
336 fn by_value_cursor_vec_u8() {
337 let bytes: Vec<u8> = (0..8).collect();
338 let (some_numbers, parser) = do_by_value::<_, SomeNumbers>(bytes);
339 assert_eq!(0, some_numbers.a);
340 assert_eq!(7, some_numbers.d);
341 assert_eq!(8, parser.0.position());
342 assert_eq!(8, parser.into_inner().len());
343 }
344
345 #[test]
346 fn by_value_slice_u8_parse_slice() {
347 let bytes: Vec<u8> = (0..24).collect();
348 let (some_numbers, parser) = do_slice_by_value::<_, SomeNumbers>(bytes.as_slice(), 3);
349 assert_eq!(3, some_numbers.len());
350 assert_eq!(0, some_numbers[0].a);
351 assert_eq!(7, some_numbers[0].d);
352 assert_eq!(8, some_numbers[1].a);
353 assert_eq!(15, some_numbers[1].d);
354 assert_eq!(16, some_numbers[2].a);
355 assert_eq!(23, some_numbers[2].d);
356 assert_eq!(24, parser.into_inner().len());
357 }
358}