blockchain_zc_parser/
cursor.rs1use crate::error::{ParseError, ParseResult};
8
9#[derive(Debug, Clone)]
14pub struct Cursor<'a> {
15 data: &'a [u8],
16 pos: usize,
17}
18
19impl<'a> Cursor<'a> {
20 #[inline]
22 pub const fn new(data: &'a [u8]) -> Self {
23 Self { data, pos: 0 }
24 }
25
26 #[inline]
28 pub const fn position(&self) -> usize {
29 self.pos
30 }
31
32 #[inline]
34 pub const fn remaining(&self) -> usize {
35 self.data.len().saturating_sub(self.pos)
36 }
37
38 #[inline]
40 pub const fn is_empty(&self) -> bool {
41 self.pos >= self.data.len()
42 }
43
44 #[inline]
46 pub fn as_slice(&self) -> &'a [u8] {
47 debug_assert!(self.pos <= self.data.len());
48 &self.data[self.pos..]
49 }
50
51 #[inline]
55 pub fn read_bytes(&mut self, n: usize) -> ParseResult<&'a [u8]> {
56 let end = self.pos.checked_add(n).ok_or(ParseError::UnexpectedEof {
57 needed: n,
58 available: self.remaining(),
59 })?;
60 if end > self.data.len() {
61 return Err(ParseError::UnexpectedEof {
62 needed: n,
63 available: self.remaining(),
64 });
65 }
66 let slice = unsafe { self.data.get_unchecked(self.pos..end) };
68 self.pos = end;
69 Ok(slice)
70 }
71
72 #[inline]
74 pub fn read_u8(&mut self) -> ParseResult<u8> {
75 if self.pos >= self.data.len() {
76 return Err(ParseError::UnexpectedEof {
77 needed: 1,
78 available: 0,
79 });
80 }
81 let b = unsafe { *self.data.get_unchecked(self.pos) };
83 self.pos += 1;
84 Ok(b)
85 }
86
87 #[inline]
89 pub fn read_u16_le(&mut self) -> ParseResult<u16> {
90 let bytes = self.read_bytes(2)?;
91 Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
92 }
93
94 #[inline]
96 pub fn read_u32_le(&mut self) -> ParseResult<u32> {
97 let bytes = self.read_bytes(4)?;
98 Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
99 }
100
101 #[inline]
103 pub fn read_i32_le(&mut self) -> ParseResult<i32> {
104 let bytes = self.read_bytes(4)?;
105 Ok(i32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
106 }
107
108 #[inline]
110 pub fn read_u64_le(&mut self) -> ParseResult<u64> {
111 let bytes = self.read_bytes(8)?;
112 Ok(u64::from_le_bytes([
113 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
114 ]))
115 }
116
117 #[inline]
119 pub fn read_i64_le(&mut self) -> ParseResult<i64> {
120 let bytes = self.read_bytes(8)?;
121 Ok(i64::from_le_bytes([
122 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
123 ]))
124 }
125
126 #[inline]
130 pub fn read_varint(&mut self) -> ParseResult<u64> {
131 match self.read_u8()? {
132 v @ 0x00..=0xfc => Ok(v as u64),
133 0xfd => self.read_u16_le().map(|v| v as u64),
134 0xfe => self.read_u32_le().map(|v| v as u64),
135 0xff => self.read_u64_le(),
136 }
137 }
138
139 #[inline]
143 pub fn read_var_bytes(&mut self, max: usize) -> ParseResult<&'a [u8]> {
144 let len_u64 = self.read_varint()?;
145 let len: usize = len_u64
146 .try_into()
147 .map_err(|_| ParseError::IntegerTooLarge { value: len_u64 })?;
148
149 if len > max {
150 return Err(ParseError::OversizedData { size: len, max });
151 }
152 self.read_bytes(len)
153 }
154
155 #[inline]
159 pub fn read_array<const N: usize>(&mut self) -> ParseResult<&'a [u8; N]> {
160 let bytes = self.read_bytes(N)?;
161 Ok(unsafe { &*(bytes.as_ptr() as *const [u8; N]) })
163 }
164
165 #[inline]
167 pub fn skip(&mut self, n: usize) -> ParseResult<()> {
168 let _ = self.read_bytes(n)?;
169 Ok(())
170 }
171
172 #[inline]
176 pub fn split(&mut self, n: usize) -> ParseResult<Cursor<'a>> {
177 let slice = self.read_bytes(n)?;
178 Ok(Cursor::new(slice))
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 #[test]
187 fn read_bytes_zero_copy() {
188 let data = [1u8, 2, 3, 4, 5, 6, 7, 8];
189 let mut c = Cursor::new(&data);
190 let slice = c.read_bytes(4).unwrap();
191 assert_eq!(slice.as_ptr(), data.as_ptr());
193 assert_eq!(slice, &[1, 2, 3, 4]);
194 assert_eq!(c.remaining(), 4);
195 }
196
197 #[test]
198 fn varint_single_byte() {
199 let data = [0xfc];
200 let mut c = Cursor::new(&data);
201 assert_eq!(c.read_varint().unwrap(), 0xfc);
202 }
203
204 #[test]
205 fn varint_two_bytes() {
206 let data = [0xfd, 0x01, 0x00];
207 let mut c = Cursor::new(&data);
208 assert_eq!(c.read_varint().unwrap(), 1);
209 }
210
211 #[test]
212 fn varint_nine_bytes() {
213 let mut data = [0u8; 9];
214 data[0] = 0xff;
215 data[1..].copy_from_slice(&u64::MAX.to_le_bytes());
216 let mut c = Cursor::new(&data);
217 assert_eq!(c.read_varint().unwrap(), u64::MAX);
218 }
219
220 #[test]
221 fn eof_error() {
222 let data = [1u8, 2];
223 let mut c = Cursor::new(&data);
224 assert!(matches!(
225 c.read_bytes(3),
226 Err(ParseError::UnexpectedEof {
227 needed: 3,
228 available: 2
229 })
230 ));
231 }
232}