1#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
3pub struct Cursor<T> {
4 t: T,
5 cursor: usize,
6 len: usize,
7}
8
9impl<T: AsRef<[u8]>> Cursor<T> {
10 fn is_exhausted_(cursor: usize, len: usize) -> bool {
11 Self::remaining_(cursor, len) <= 0
12 }
13
14 fn remaining_(cursor: usize, len: usize) -> isize {
15 len as isize - cursor as isize
16 }
17
18 fn peek_(len: usize, cursor: usize, t: &T, n: usize) -> Option<&[u8]> {
19 if n as isize > Self::remaining_(cursor, len) {
20 None
21 } else {
22 Some(&t.as_ref()[cursor..cursor + n])
23 }
24 }
25
26 fn skip_(cursor: &mut usize, len: usize, n: usize) -> usize {
27 if Self::is_exhausted_(*cursor, len) {
28 0
29 } else if *cursor + n > len {
30 let left = len - *cursor;
31 *cursor += left;
32 left
33 } else {
34 *cursor += n;
35 n
36 }
37 }
38
39 fn peek_until_end_(cursor: usize, len: usize, t: &T) -> &[u8] {
40 if Self::is_exhausted_(cursor, len) {
41 &[]
42 } else {
43 &t.as_ref()[cursor..]
44 }
45 }
46
47 fn seek_to_end_(cursor: &mut usize, len: usize) {
48 *cursor = len;
49 }
50
51 fn take_until_end_<'a, 'b>(cursor: &'a mut usize, len: usize, t: &'b T) -> &'b [u8] {
52 let out = Self::peek_until_end_(*cursor, len, t);
53 Self::seek_to_end_(cursor, len);
54
55 out
56 }
57
58 pub fn new(t: T) -> Cursor<T> {
60 let len = t.as_ref().len();
61 Cursor { t, cursor: 0, len }
62 }
63
64 pub fn into_inner(self) -> T {
66 self.t
67 }
68
69 #[allow(clippy::should_implement_trait)]
74 pub fn next(&mut self) -> Option<u8> {
75 self.take_exact(1).and_then(|a| match a {
76 | &[a] => Some(a),
77 | _ => None,
78 })
79 }
80
81 pub fn take(&mut self, n: usize) -> &[u8] {
86 Self::peek_(self.len, self.cursor, &self.t, n).map(|a| {
87 Self::skip_(&mut self.cursor, self.len, n);
88 a
89 })
90 .unwrap_or_else(|| {
91 Self::take_until_end_(&mut self.cursor,
92 self.len,
93 &self.t)
94 })
95 }
96
97 pub fn take_exact(&mut self, n: usize) -> Option<&[u8]> {
102 Self::peek_(self.len, self.cursor, &self.t, n).map(|a| {
103 Self::skip_(&mut self.cursor, self.len, n);
104 a
105 })
106 }
107
108 pub fn peek(&self, n: usize) -> &[u8] {
114 Self::peek_(self.len, self.cursor, &self.t, n).unwrap_or_else(|| self.peek_until_end())
115 }
116
117 pub fn peek_exact(&self, n: usize) -> Option<&[u8]> {
123 Self::peek_(self.len, self.cursor, &self.t, n)
124 }
125
126 pub fn skip(&mut self, n: usize) -> usize {
135 Self::skip_(&mut self.cursor, self.len, n)
136 }
137
138 pub fn take_while(&mut self, mut f: impl FnMut(u8) -> bool) -> &[u8] {
142 if self.is_exhausted() {
143 return &[];
144 }
145
146 (self.cursor..self.len).into_iter()
147 .take_while(|ix| f(self.t.as_ref()[*ix]))
148 .last()
149 .map(|end_ix| {
150 let out = &self.t.as_ref()[self.cursor..=end_ix];
151 self.cursor = end_ix + 1;
152 out
153 })
154 .unwrap_or(&[])
155 }
156
157 pub fn is_exhausted(&self) -> bool {
162 Self::is_exhausted_(self.cursor, self.len)
163 }
164
165 pub fn remaining(&self) -> usize {
169 Self::remaining_(self.cursor, self.len).max(0) as usize
170 }
171
172 pub fn peek_until_end(&self) -> &[u8] {
176 Self::peek_until_end_(self.cursor, self.len, &self.t)
177 }
178
179 pub fn take_until_end(&mut self) -> &[u8] {
184 Self::take_until_end_(&mut self.cursor, self.len, &self.t)
185 }
186
187 pub fn position(&self) -> usize {
190 self.cursor
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
199 pub fn peek_until_end() {
200 let cur = Cursor::new(vec![]);
201 assert_eq!(cur.peek_until_end(), &[]);
202
203 let cur = Cursor::new(vec![1, 2, 3]);
204 assert_eq!(cur.peek_until_end(), &[1, 2, 3]);
205
206 let mut cur = Cursor::new(vec![1, 2, 3]);
207 cur.skip(1);
208 assert_eq!(cur.peek_until_end(), &[2, 3]);
209 }
210
211 #[test]
212 pub fn take_until_end() {
213 let mut cur = Cursor::new(vec![]);
214 assert_eq!(cur.take_until_end(), &[]);
215 assert_eq!(cur.take_until_end(), &[]);
216 assert_eq!(cur.take_until_end(), &[]);
217
218 let mut cur = Cursor::new(vec![1, 2, 3]);
219 assert_eq!(cur.take_until_end(), &[1, 2, 3]);
220
221 let mut cur = Cursor::new(vec![1, 2, 3]);
222 cur.skip(1);
223 assert_eq!(cur.take_until_end(), &[2, 3]);
224 assert_eq!(cur.peek_until_end(), &[]);
225 }
226
227 #[test]
228 pub fn next() {
229 let mut cur = Cursor::new(vec![1]);
230 assert_eq!(cur.next(), Some(1));
231 assert_eq!(cur.next(), None);
232 assert_eq!(cur.next(), None);
233 }
234
235 #[test]
236 pub fn take() {
237 let mut cur = Cursor::new(vec![1, 2, 3]);
238 assert_eq!(cur.take(2), &[1, 2]);
239 assert_eq!(cur.take(1), &[3]);
240 assert_eq!(cur.take(1), &[]);
241 }
242
243 #[test]
244 pub fn peek() {
245 let mut cur = Cursor::new(vec![1, 2, 3]);
246 assert_eq!(cur.peek(2), &[1, 2]);
247 assert_eq!(cur.peek(1), &[1]);
248 assert_eq!(cur.peek(4), &[1, 2, 3]);
249 cur.take(3);
250 assert_eq!(cur.peek(1), &[]);
251 }
252
253 #[test]
254 pub fn take_exact() {
255 let mut cur = Cursor::new(vec![1, 2, 3]);
256 assert_eq!(cur.take_exact(2), Some([1, 2].as_ref()));
257 assert_eq!(cur.take_exact(2), None);
258 assert_eq!(cur.take_exact(1), Some([3].as_ref()));
259 }
260
261 #[test]
262 pub fn peek_exact() {
263 let cur = Cursor::new(vec![1, 2, 3]);
264 assert_eq!(cur.peek_exact(3), Some([1, 2, 3].as_ref()));
265 assert_eq!(cur.peek_exact(1), Some([1].as_ref()));
266 assert_eq!(cur.peek_exact(4), None);
267 }
268
269 #[test]
270 pub fn take_while() {
271 let til_slash = |c: &mut Cursor<&str>| {
272 core::str::from_utf8(c.take_while(|b| (b as char) != '/')).unwrap()
273 .to_string()
274 };
275
276 let mut cur = Cursor::new("abc/def");
277 assert_eq!(til_slash(&mut cur), "abc".to_string());
278 cur.skip(1);
279 assert_eq!(til_slash(&mut cur), "def".to_string());
280 assert_eq!(til_slash(&mut cur), "".to_string());
281
282 let mut cur = Cursor::new("a");
283 assert_eq!(til_slash(&mut cur), "a");
284
285 let mut cur = Cursor::new("");
286 assert_eq!(til_slash(&mut cur), "");
287
288 let mut cur = Cursor::new("ab");
289 assert_eq!(til_slash(&mut cur), "ab");
290
291 let mut cur = Cursor::new("/abcd");
292 assert_eq!(til_slash(&mut cur), "");
293 }
294
295 #[test]
296 pub fn seek() {
297 let mut cur = Cursor::new(vec![1, 2, 3, 4]);
298 assert_eq!(cur.skip(0), 0); assert_eq!(cur.skip(1), 1); assert_eq!(cur.skip(2), 2); assert_eq!(cur.skip(1), 1); assert_eq!(cur.skip(1), 0); }
304}