1use core::borrow::{Borrow, BorrowMut};
19
20use crate::error::*;
21use core::convert::TryInto;
22
23pub struct ReadBuf<T> {
25 buf: T,
26 read_off: usize,
27 left: usize,
28}
29
30impl<T> ReadBuf<T>
31where
32 T: Borrow<[u8]>,
33{
34 pub fn new(buf: T) -> Self {
35 let left = buf.borrow().len();
36
37 Self {
38 buf,
39 read_off: 0,
40 left,
41 }
42 }
43
44 pub fn reset(&mut self) {
45 self.read_off = 0;
46 self.left = self.buf.borrow().len();
47 }
48
49 pub fn load<Q>(&mut self, pb: &ReadBuf<Q>) -> Result<(), Error>
50 where
51 T: BorrowMut<[u8]>,
52 Q: Borrow<[u8]>,
53 {
54 if self.buf.borrow().len() < pb.read_off + pb.left {
55 Err(ErrorCode::BufferTooSmall)?;
56 }
57
58 self.buf.borrow_mut()[0..pb.read_off + pb.left]
59 .copy_from_slice(&pb.buf.borrow()[..pb.read_off + pb.left]);
60 self.read_off = pb.read_off;
61 self.left = pb.left;
62
63 Ok(())
64 }
65
66 pub fn set_len(&mut self, left: usize) {
67 self.left = left;
68 }
69
70 pub fn read_off(&self) -> usize {
71 self.read_off
72 }
73
74 pub fn slice_range(&self) -> (usize, usize) {
75 (self.read_off, self.read_off + self.left)
76 }
77
78 pub fn as_slice(&self) -> &[u8] {
80 &self.buf.borrow()[self.read_off..(self.read_off + self.left)]
81 }
82
83 pub fn as_mut_slice(&mut self) -> &mut [u8]
85 where
86 T: BorrowMut<[u8]>,
87 {
88 &mut self.buf.borrow_mut()[self.read_off..(self.read_off + self.left)]
89 }
90
91 pub fn parsed_as_slice(&self) -> &[u8] {
92 &self.buf.borrow()[0..self.read_off]
93 }
94
95 pub fn tail(&mut self, size: usize) -> Result<&[u8], Error> {
96 if size <= self.left {
97 let end_offset = self.read_off + self.left;
98 let tail = &self.buf.borrow()[(end_offset - size)..end_offset];
99 self.left -= size;
100 return Ok(tail);
101 }
102 Err(ErrorCode::TruncatedPacket.into())
103 }
104
105 fn advance(&mut self, len: usize) {
106 self.read_off += len;
107 self.left -= len;
108 }
109
110 pub fn parse_head_with<F, R>(&mut self, size: usize, f: F) -> Result<R, Error>
111 where
112 F: FnOnce(&mut Self) -> R,
113 {
114 if self.left >= size {
115 let data = f(self);
116 self.advance(size);
117 return Ok(data);
118 }
119 Err(ErrorCode::TruncatedPacket.into())
120 }
121
122 pub fn parse_as_array<F, R, const N: usize>(&mut self, f: F) -> Result<R, Error>
123 where
124 F: FnOnce([u8; N]) -> R,
125 {
126 if self.left >= N {
127 let end_offset = self.read_off + N;
128 let data = f(self.buf.borrow()[self.read_off..end_offset]
129 .try_into()
130 .unwrap());
131 self.advance(N);
132 return Ok(data);
133 }
134 Err(ErrorCode::TruncatedPacket.into())
135 }
136
137 pub fn le_u8(&mut self) -> Result<u8, Error> {
138 self.parse_head_with(1, |x| x.buf.borrow()[x.read_off])
139 }
140
141 pub fn le_u16(&mut self) -> Result<u16, Error> {
142 self.parse_as_array(u16::from_le_bytes)
143 }
144
145 pub fn le_u32(&mut self) -> Result<u32, Error> {
146 self.parse_as_array(u32::from_le_bytes)
147 }
148
149 pub fn le_u64(&mut self) -> Result<u64, Error> {
150 self.parse_as_array(u64::from_le_bytes)
151 }
152}
153
154pub type ParseBuf<'a> = ReadBuf<&'a mut [u8]>;
155
156#[cfg(test)]
157mod tests {
158 use crate::utils::storage::ParseBuf;
159
160 #[test]
161 fn test_parse_with_success() {
162 let mut test_slice = [0x01, 65, 0, 0xbe, 0xba, 0xfe, 0xca, 0xa, 0xb, 0xc, 0xd];
163 let mut buf = ParseBuf::new(&mut test_slice);
164
165 assert_eq!(buf.le_u8().unwrap(), 0x01);
166 assert_eq!(buf.le_u16().unwrap(), 65);
167 assert_eq!(buf.le_u32().unwrap(), 0xcafebabe);
168 assert_eq!(buf.as_slice(), [0xa, 0xb, 0xc, 0xd]);
169 }
170
171 #[test]
172 fn test_parse_with_overrun() {
173 let mut test_slice = [0x01, 65];
174 let mut buf = ParseBuf::new(&mut test_slice);
175
176 assert_eq!(buf.le_u8().unwrap(), 0x01);
177
178 if buf.le_u16().is_ok() {
179 panic!("This should have returned error")
180 }
181
182 if buf.le_u32().is_ok() {
183 panic!("This should have returned error")
184 }
185
186 assert_eq!(buf.le_u8().unwrap(), 65);
188
189 if buf.le_u8().is_ok() {
190 panic!("This should have returned error")
191 }
192 assert_eq!(buf.as_slice(), [] as [u8; 0]);
193 }
194
195 #[test]
196 fn test_tail_with_success() {
197 let mut test_slice = [0x01, 65, 0, 0xbe, 0xba, 0xfe, 0xca, 0xa, 0xb, 0xc, 0xd];
198 let mut buf = ParseBuf::new(&mut test_slice);
199
200 assert_eq!(buf.le_u8().unwrap(), 0x01);
201 assert_eq!(buf.le_u16().unwrap(), 65);
202 assert_eq!(buf.le_u32().unwrap(), 0xcafebabe);
203
204 assert_eq!(buf.tail(2).unwrap(), [0xc, 0xd]);
205 assert_eq!(buf.as_slice(), [0xa, 0xb]);
206
207 assert_eq!(buf.tail(2).unwrap(), [0xa, 0xb]);
208 assert_eq!(buf.as_slice(), [] as [u8; 0]);
209 }
210
211 #[test]
212 fn test_tail_with_overrun() {
213 let mut test_slice = [0x01, 65, 0, 0xbe, 0xba, 0xfe, 0xca, 0xa, 0xb, 0xc, 0xd];
214 let mut buf = ParseBuf::new(&mut test_slice);
215
216 assert_eq!(buf.le_u8().unwrap(), 0x01);
217 assert_eq!(buf.le_u16().unwrap(), 65);
218 assert_eq!(buf.le_u32().unwrap(), 0xcafebabe);
219 if buf.tail(5).is_ok() {
220 panic!("This should have returned error")
221 }
222 assert_eq!(buf.tail(2).unwrap(), [0xc, 0xd]);
223 }
224
225 #[test]
226 fn test_parsed_as_slice() {
227 let mut test_slice = [0x01, 65, 0, 0xbe, 0xba, 0xfe, 0xca, 0xa, 0xb, 0xc, 0xd];
228 let mut buf = ParseBuf::new(&mut test_slice);
229
230 assert_eq!(buf.parsed_as_slice(), [] as [u8; 0]);
231 assert_eq!(buf.le_u8().unwrap(), 0x1);
232 assert_eq!(buf.le_u16().unwrap(), 65);
233 assert_eq!(buf.le_u32().unwrap(), 0xcafebabe);
234 assert_eq!(buf.parsed_as_slice(), [0x01, 65, 0, 0xbe, 0xba, 0xfe, 0xca]);
235 }
236}