1#[cfg(not(feature = "std"))]
2use core::{fmt::Debug, prelude::rust_2021::derive, result::Result::Ok};
3
4use byteorder::ByteOrder;
5
6use super::BufferTooSmall;
7
8#[derive(Debug)]
11pub struct Cursor<T> {
12 buffer: T,
13 pos: usize,
14}
15
16impl<T: AsRef<[u8]>> Cursor<T> {
17 pub fn new(buffer: T) -> Self {
19 Self { buffer, pos: 0 }
20 }
21
22 #[allow(clippy::len_without_is_empty)]
23 pub fn len(&self) -> usize {
25 self.buffer.as_ref().len()
26 }
27
28 pub fn remaining(&self) -> usize {
30 self.buffer.as_ref().len() - self.pos
31 }
32
33 pub fn check_remaining(
35 &self,
36 expected: usize,
37 ) -> Result<(), BufferTooSmall> {
38 if self.remaining() < expected {
39 return Err(BufferTooSmall {
40 size: self.len(),
41 expected: self.pos + expected,
42 });
43 }
44
45 Ok(())
46 }
47
48 pub fn position(&self) -> usize {
50 self.pos
51 }
52
53 pub fn set_position(&mut self, position: usize) {
55 self.pos = position
56 }
57
58 pub fn skip(&mut self, count: usize) {
60 self.pos += count;
61 }
62
63 pub fn read_bytes(&mut self, dst: &mut [u8]) {
67 dst.copy_from_slice(
68 &self.buffer.as_ref()[self.pos..(self.pos + dst.len())],
69 );
70 self.pos += dst.len();
71 }
72
73 pub fn read_u8(&mut self) -> u8 {
77 let val = self.buffer.as_ref()[self.pos];
78 self.pos += 1;
79 val
80 }
81
82 pub fn read_u16<B: ByteOrder>(&mut self) -> u16 {
86 let val = B::read_u16(&self.buffer.as_ref()[self.pos..]);
87 self.pos += 2;
88 val
89 }
90
91 pub fn read_u24<B: ByteOrder>(&mut self) -> u32 {
95 let val = B::read_u24(&self.buffer.as_ref()[self.pos..]);
96 self.pos += 3;
97 val
98 }
99
100 pub fn read_u32<B: ByteOrder>(&mut self) -> u32 {
104 let val = B::read_u32(&self.buffer.as_ref()[self.pos..]);
105 self.pos += 4;
106 val
107 }
108
109 pub fn read_u64<B: ByteOrder>(&mut self) -> u64 {
113 let val = B::read_u64(&self.buffer.as_ref()[self.pos..]);
114 self.pos += 8;
115 val
116 }
117
118 pub fn peek_u8(&self, offset: usize) -> u8 {
122 self.buffer.as_ref()[self.pos + offset]
123 }
124
125 pub fn peek_u16<B: ByteOrder>(&self, offset: usize) -> u16 {
129 B::read_u16(&self.buffer.as_ref()[(self.pos + offset)..])
130 }
131
132 pub fn peek_u24<B: ByteOrder>(&self, offset: usize) -> u32 {
136 B::read_u24(&self.buffer.as_ref()[(self.pos + offset)..])
137 }
138
139 pub fn peek_u32<B: ByteOrder>(&self, offset: usize) -> u32 {
143 B::read_u32(&self.buffer.as_ref()[(self.pos + offset)..])
144 }
145}
146
147impl Cursor<&mut [u8]> {
148 pub fn write_bytes(&mut self, src: &[u8]) {
152 self.buffer[self.pos..(self.pos + src.len())].copy_from_slice(src);
153 self.pos += src.len();
154 }
155
156 pub fn write_u8(&mut self, val: u8) {
160 self.buffer[self.pos] = val;
161 self.pos += 1;
162 }
163
164 pub fn write_u16<B: ByteOrder>(&mut self, val: u16) {
168 B::write_u16(&mut self.buffer[self.pos..], val);
169 self.pos += 2;
170 }
171
172 pub fn write_u24<B: ByteOrder>(&mut self, val: u32) {
176 B::write_u24(&mut self.buffer[self.pos..], val);
177 self.pos += 3;
178 }
179
180 pub fn write_u32<B: ByteOrder>(&mut self, val: u32) {
184 B::write_u32(&mut self.buffer[self.pos..], val);
185 self.pos += 4;
186 }
187
188 pub fn write_u64<B: ByteOrder>(&mut self, val: u64) {
192 B::write_u64(&mut self.buffer[self.pos..], val);
193 self.pos += 8;
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use byteorder::{BigEndian, LittleEndian};
200
201 use super::*;
202
203 #[test]
204 fn test_read() {
205 let buffer = [1u8, 0, 1, 0, 1, 0, 0, 0, 0, 2, 2, 0, 0, 0];
206 let mut cursor = Cursor::new(&buffer[..]);
207
208 assert_eq!(cursor.len(), 14);
209 assert_eq!(cursor.remaining(), 14);
210
211 assert_eq!(cursor.read_u8(), 1);
212 assert_eq!(cursor.remaining(), 13);
213
214 assert_eq!(cursor.read_u16::<BigEndian>(), 1);
215 cursor.skip(1);
216 assert_eq!(cursor.read_u16::<LittleEndian>(), 1);
217 assert!(cursor.check_remaining(8).is_ok());
218
219 assert_eq!(cursor.read_u32::<BigEndian>(), 2);
220 assert_eq!(cursor.read_u32::<LittleEndian>(), 2);
221 assert!(cursor.check_remaining(1).is_err());
222
223 cursor.set_position(1);
224 let mut buf = [0u8; 4];
225 cursor.read_bytes(&mut buf);
226 assert_eq!(buf, [0, 1, 0, 1]);
227 }
228
229 #[test]
230 fn test_peek() {
231 let buffer = [1u8, 0, 1, 0, 1, 0, 0, 0, 0, 2, 2, 0, 0, 0];
232 let mut cursor = Cursor::new(&buffer[..]);
233
234 assert_eq!(cursor.peek_u8(1), 0);
235 assert_eq!(cursor.peek_u16::<BigEndian>(2), 256);
236 assert_eq!(cursor.peek_u32::<LittleEndian>(6), 0x02000000);
237
238 cursor.set_position(5);
239 assert_eq!(cursor.peek_u8(1), 0);
240 assert_eq!(cursor.peek_u16::<BigEndian>(3), 2);
241 assert_eq!(cursor.peek_u32::<LittleEndian>(5), 2);
242 }
243
244 #[test]
245 fn test_write() {
246 let mut buffer = [0u8; 16];
247 let mut cursor = Cursor::new(&mut buffer[..]);
248
249 cursor.write_u8(1);
250 cursor.write_u16::<BigEndian>(5);
251 cursor.write_u32::<LittleEndian>(16);
252 cursor.write_bytes(&[1, 2, 3, 4, 5]);
253
254 assert_eq!(cursor.position(), 12);
255 assert_eq!(buffer, [1, 0, 5, 16, 0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0]);
256 }
257}