1use std::fmt::Debug;
6use std::sync::Arc;
7use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned};
8
9pub type PolicyData = Arc<Vec<u8>>;
10pub type PolicyOffset = u32;
11
12#[derive(Clone, Debug, PartialEq)]
13pub struct PolicyCursor {
14 data: PolicyData,
15 offset: PolicyOffset,
16}
17
18impl PolicyCursor {
19 pub fn new(data: PolicyData) -> Self {
21 Self { data, offset: 0 }
22 }
23
24 pub fn new_at(data: PolicyData, offset: PolicyOffset) -> Self {
26 Self { data, offset }
27 }
28
29 pub fn parse<P: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned>(
31 mut self,
32 ) -> Option<(P, Self)> {
33 let (output, _) = P::read_from_prefix(self.remaining_slice()).ok()?;
34 self.seek_forward(std::mem::size_of_val(&output)).ok()?;
35 Some((output, self))
36 }
37
38 pub fn parse_slice<PS: Clone + Debug + FromBytes + Immutable + PartialEq + Unaligned>(
41 mut self,
42 count: usize,
43 ) -> Option<(Vec<PS>, Self)> {
44 let (slice, _) = <[PS]>::ref_from_prefix_with_elems(self.remaining_slice(), count).ok()?;
45 let size = std::mem::size_of_val(&slice);
46 let slice = slice.to_owned();
47 self.seek_forward(size).ok()?;
48 Some((slice, self))
49 }
50
51 pub fn offset(&self) -> PolicyOffset {
52 self.offset
53 }
54
55 pub fn len(&self) -> usize {
56 self.data.len() - self.offset as usize
57 }
58
59 pub fn seek_forward(&mut self, num_bytes: usize) -> Result<(), std::io::Error> {
61 if num_bytes > self.len() {
62 return Err(std::io::Error::from(std::io::ErrorKind::UnexpectedEof));
63 }
64 self.offset += num_bytes as PolicyOffset;
65 Ok(())
66 }
67
68 pub fn data(&self) -> &PolicyData {
69 &self.data
70 }
71
72 fn remaining_slice(&self) -> &[u8] {
74 let s: &[u8] = self.data.as_ref();
75 let p = self.offset as usize;
76 &s[p..]
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use zerocopy::little_endian as le;
84
85 #[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
86 #[repr(C, packed)]
87 struct SomeNumbers {
88 a: u8,
89 b: le::U32,
90 c: le::U16,
91 d: u8,
92 }
93
94 fn do_by_value<
96 T: Clone + Debug + FromBytes + KnownLayout + Immutable + PartialEq + Unaligned,
97 >(
98 data: Vec<u8>,
99 ) -> (T, PolicyCursor) {
100 let parser = PolicyCursor::new(Arc::new(data));
101 parser.parse::<T>().expect("some numbers")
102 }
103 fn do_slice_by_value<T: Clone + Debug + FromBytes + Immutable + PartialEq + Unaligned>(
104 data: Vec<u8>,
105 count: usize,
106 ) -> (Vec<T>, PolicyCursor) {
107 let parser = PolicyCursor::new(Arc::new(data));
108 parser.parse_slice::<T>(count).expect("some numbers")
109 }
110
111 #[test]
112 fn by_value_cursor_vec_u8() {
113 let bytes: Vec<u8> = (0..8).collect();
114 let (some_numbers, parser) = do_by_value::<SomeNumbers>(bytes);
115 assert_eq!(0, some_numbers.a);
116 assert_eq!(7, some_numbers.d);
117 assert_eq!(8, parser.offset);
118 assert_eq!(8, parser.data.len());
119 }
120
121 #[test]
122 fn by_value_slice_u8_parse_slice() {
123 let bytes: Vec<u8> = (0..24).collect();
124 let (some_numbers, parser) = do_slice_by_value::<SomeNumbers>(bytes, 3);
125 assert_eq!(3, some_numbers.len());
126 assert_eq!(0, some_numbers[0].a);
127 assert_eq!(7, some_numbers[0].d);
128 assert_eq!(8, some_numbers[1].a);
129 assert_eq!(15, some_numbers[1].d);
130 assert_eq!(16, some_numbers[2].a);
131 assert_eq!(23, some_numbers[2].d);
132 assert_eq!(24, parser.data.len());
133 }
134}