util_cursor/lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3
4use core::fmt;
5
6pub struct Cursor<T> {
7 pub data: T,
8 pub offset: usize,
9}
10
11impl<'a, T> Cursor<&'a [T]> {
12 /// Returns remaining slice from the current offset.
13 /// It doesn't change the offset.
14 ///
15 /// # Examples
16 ///
17 /// ```
18 /// use util_cursor::Cursor;
19 ///
20 /// let mut cursor = Cursor::new([1, 2].as_ref());
21 ///
22 /// assert_eq!(cursor.remaining_slice(), &[1, 2]);
23 /// cursor.offset = 42;
24 /// assert!(cursor.remaining_slice().is_empty());
25 /// ```
26 #[inline]
27 pub fn remaining_slice(&self) -> &'a [T] {
28 unsafe { self.data.get_unchecked(self.offset.min(self.data.len())..) }
29 }
30
31 /// Read slice from the current offset.
32 ///
33 /// # Example
34 /// ```
35 /// use util_cursor::Cursor;
36 /// let mut view = Cursor::new([1, 2, 3].as_ref());
37 ///
38 /// assert_eq!(view.read_slice(2), Some([1, 2].as_ref()));
39 /// assert_eq!(view.read_slice(3), None);
40 /// ```
41 #[inline]
42 pub fn read_slice(&mut self, len: usize) -> Option<&'a [T]> {
43 let total_len = self.offset + len;
44 let slice = self.data.get(self.offset..total_len)?;
45 self.offset = total_len;
46 Some(slice)
47 }
48}
49
50impl<T> Cursor<T> {
51 /// Creates a new [`Cursor<T>`].
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use util_cursor::Cursor;
57 ///
58 /// let cursor = Cursor::new([1, 2].as_ref());
59 /// ```
60 #[inline]
61 pub const fn new(data: T) -> Self {
62 Self { data, offset: 0 }
63 }
64}
65
66impl<T> From<T> for Cursor<T> {
67 #[inline]
68 fn from(data: T) -> Self {
69 Self::new(data)
70 }
71}
72
73impl<T: Clone> Clone for Cursor<T> {
74 fn clone(&self) -> Self {
75 Self {
76 data: self.data.clone(),
77 offset: self.offset,
78 }
79 }
80}
81
82impl<T: fmt::Debug> fmt::Debug for Cursor<T> {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.debug_struct("Cursor")
85 .field("data", &self.data)
86 .field("offset", &self.offset)
87 .finish()
88 }
89}