Skip to main content

kstd/io/
cursor.rs

1// more or less copied from the Rust stdlib
2
3use crate::io::read::Read;
4use crate::io::{Error, Seek, Write};
5use crate::io::{Result, SeekFrom};
6
7pub struct Cursor<T> {
8    inner: T,
9    pos: u64,
10}
11
12impl<T> Cursor<T> {
13    pub const fn new(inner: T) -> Self {
14        Self { inner, pos: 0 }
15    }
16
17    pub fn into_inner(self) -> T {
18        self.inner
19    }
20
21    pub const fn get_ref(&self) -> &T {
22        &self.inner
23    }
24
25    pub fn get_mut(&mut self) -> &mut T {
26        &mut self.inner
27    }
28
29    pub fn position(&self) -> u64 {
30        self.pos
31    }
32
33    pub fn set_position(&mut self, pos: u64) {
34        self.pos = pos;
35    }
36}
37
38impl<T> Cursor<T>
39where
40    T: AsRef<[u8]>,
41{
42    pub fn remaining_slice(&self) -> &[u8] {
43        let len = self.pos.min(self.inner.as_ref().len() as u64);
44        &self.inner.as_ref()[(len as usize)..]
45    }
46
47    pub fn is_empty(&self) -> bool {
48        self.pos >= self.inner.as_ref().len() as u64
49    }
50}
51
52impl<T> Clone for Cursor<T>
53where
54    T: Clone,
55{
56    fn clone(&self) -> Self {
57        Self {
58            inner: self.inner.clone(),
59            pos: self.pos,
60        }
61    }
62
63    fn clone_from(&mut self, source: &Self) {
64        self.inner.clone_from(&source.inner);
65        self.pos = source.pos;
66    }
67}
68
69impl<T> Seek for Cursor<T>
70where
71    T: AsRef<[u8]>,
72{
73    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
74        let new_pos = match pos {
75            SeekFrom::Start(n) => n,
76            SeekFrom::End(n) => {
77                let p = (self.inner.as_ref().len() as i64) - n;
78                if p < 0 {
79                    return Err(Error::InvalidOffset);
80                }
81                p as u64
82            }
83            SeekFrom::Current(n) => self.pos as u64 + n as u64,
84        };
85        if new_pos >= self.inner.as_ref().len() as u64 {
86            Err(Error::InvalidOffset)
87        } else {
88            self.pos = new_pos;
89            Ok(self.pos)
90        }
91    }
92}
93
94impl<T> Read<u8> for Cursor<T>
95where
96    T: AsRef<[u8]>,
97{
98    fn read(&mut self, buf: &mut dyn AsMut<[u8]>) -> Result<usize> {
99        let data = self.inner.as_ref();
100        let buffer = buf.as_mut();
101        let len = (data.len() as u64 - self.pos).min(buffer.len() as u64) as usize;
102        let target_buffer = &mut buffer[..len];
103        target_buffer.copy_from_slice(&data[(self.pos as usize)..(self.pos as usize + len)]);
104        self.pos += len as u64;
105        Ok(len)
106    }
107}
108
109impl<T> Write<u8> for Cursor<T>
110where
111    T: AsMut<[u8]>,
112{
113    fn write(&mut self, buf: &dyn AsRef<[u8]>) -> Result<usize> {
114        let data = self.inner.as_mut();
115        let buffer = buf.as_ref();
116        let len = (data.len() as u64 - self.pos).min(buffer.len() as u64) as usize;
117        let target_buffer = &mut data[(self.pos as usize)..(self.pos as usize + len)];
118        target_buffer.copy_from_slice(&buffer[..len]);
119        self.pos += len as u64;
120        Ok(len)
121    }
122
123    fn flush(&mut self) -> Result<()> {
124        Ok(())
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131    use alloc::vec;
132
133    #[test]
134    fn test_read() {
135        let data = &[0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
136        let mut buf = [0u8; 4];
137        let mut c = Cursor::new(data);
138
139        let read1 = c.read(&mut buf);
140        assert_eq!(Ok(4), read1);
141        assert_eq!(&[0, 1, 2, 3], &buf);
142
143        let read2 = c.read(&mut buf);
144        assert_eq!(Ok(4), read2);
145        assert_eq!(&[4, 5, 6, 7], &buf);
146
147        let read3 = c.read(&mut buf);
148        assert_eq!(Ok(2), read3);
149        assert_eq!(&[8, 9, 6, 7], &buf);
150    }
151
152    #[test]
153    fn test_read_vec() {
154        let data = vec![0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9];
155        let mut buf = [0u8; 4];
156        let mut c = Cursor::new(data);
157
158        let read1 = c.read(&mut buf);
159        assert_eq!(Ok(4), read1);
160        assert_eq!(&[0, 1, 2, 3], &buf);
161
162        let read2 = c.read(&mut buf);
163        assert_eq!(Ok(4), read2);
164        assert_eq!(&[4, 5, 6, 7], &buf);
165
166        let read3 = c.read(&mut buf);
167        assert_eq!(Ok(2), read3);
168        assert_eq!(&[8, 9, 6, 7], &buf);
169    }
170}