1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use super::*;

#[derive(Debug, Default)]
pub struct Cursor<T> {
    pub data: T,
    pub offset: usize,
}

impl<T: AsMut<[u8]>> Cursor<T> {
    /// Writes a slice into the data view.
    ///
    /// # Examples
    ///
    /// ```
    /// use bin_layout::{Cursor, ErrorKind};
    ///
    /// let mut view = Cursor::new([0; 3]);
    ///
    /// assert_eq!(view.write_slice([4, 2]), Ok(()));
    /// assert_eq!(view.write_slice([1, 2, 3]), Err(ErrorKind::InsufficientBytes));
    /// 
    /// assert_eq!(view.data, [4, 2, 0]);
    /// assert_eq!(view.offset, 2);
    /// ```
    #[inline]
    pub fn write_slice(&mut self, slice: impl AsRef<[u8]>) -> Result<()> {
        let data = self.data.as_mut();
        let src = slice.as_ref();
        let count = src.len();
        unsafe {
            let dst = data.as_mut_ptr().add(self.offset);
            ret_err_or_add!{ (self.offset; + count) > data.len() };            
            ptr::copy_nonoverlapping(src.as_ptr(), dst, count);
        }
        Ok(())
    }
}

impl<'de> Cursor<&'de [u8]> {
    /// Returns remaining slice from the current offset.
    /// It doesn't change the offset.
    ///
    /// # Examples
    ///
    /// ```
    /// use bin_layout::Cursor;
    ///
    /// let mut view = Cursor::new([1, 2].as_ref());
    ///
    /// assert_eq!(view.remaining_slice(), &[1, 2]);
    /// view.offset = 42;
    /// assert!(view.remaining_slice().is_empty());
    /// ```
    #[inline]
    pub fn remaining_slice(&self) -> &'de [u8] {
        unsafe { self.data.get_unchecked(self.offset.min(self.data.len())..) }
    }

    /// Read slice from the current offset.
    ///
    /// # Example
    /// ```
    /// use bin_layout::Cursor;
    /// let mut view = Cursor::new([1, 2, 3].as_ref());
    ///
    /// assert_eq!(view.read_slice(2), Ok([1, 2].as_ref()));
    /// assert!(view.read_slice(3).is_err());
    /// ```
    #[inline]
    pub fn read_slice(&mut self, len: usize) -> Result<&'de [u8]> {
        let total_len = self.offset + len;
        let slice = self.data.get(self.offset..total_len).ok_or(InsufficientBytes)?;
        self.offset = total_len;
        Ok(slice)
    }
}

impl<T> Cursor<T> {
    #[inline]
    pub const fn new(data:T) -> Self {
        Self {
            data,
            offset: 0,
        }
    }
}

impl<T> From<T> for Cursor<T> {
    #[inline]
    fn from(data: T) -> Self {
        Self::new(data)
    }
}