core2/io/
cursor.rs

1use super::{BufRead, Error, ErrorKind, Read, Result, Seek, SeekFrom, Write};
2use core::cmp;
3
4/// A `Cursor` wraps an in-memory buffer and provides it with a
5/// [`Seek`] implementation.
6///
7/// `Cursor`s are used with in-memory buffers, anything implementing
8/// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
9/// allowing these buffers to be used anywhere you might use a reader or writer
10/// that does actual I/O.
11///
12/// The standard library implements some I/O traits on various types which
13/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
14/// `Cursor<`[`&[u8]`][bytes]`>`.
15///
16/// # Examples
17///
18/// We may want to write bytes to a [`File`] in our production
19/// code, but use an in-memory buffer in our tests. We can do this with
20/// `Cursor`:
21///
22/// [bytes]: crate::slice
23/// [`File`]: crate::fs::File
24///
25/// ```
26/// use std::io::prelude::*;
27/// use core2::io::{self, Seek, SeekFrom, Write};
28/// use std::fs::File;
29///
30/// // a library function we've written
31/// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> {
32///     writer.seek(SeekFrom::End(-10))?;
33///
34///     for i in 0..10 {
35///         writer.write(&[i])?;
36///     }
37///
38///     // all went well
39///     Ok(())
40/// }
41///
42/// # #[cfg(feature = "std")]
43/// # fn foo() -> io::Result<()> {
44/// // Here's some code that uses this library function.
45/// //
46/// // We might want to use a BufReader here for efficiency, but let's
47/// // keep this example focused.
48/// let mut file = File::create("foo.txt").map_err(|e| io::Error::from(e))?;
49///
50/// write_ten_bytes_at_end(&mut file)?;
51/// # Ok(())
52/// # }
53///
54/// // now let's write a test
55/// #[test]
56/// fn test_writes_bytes() {
57///     // setting up a real File is much slower than an in-memory buffer,
58///     // let's use a cursor instead
59///     use core2::io::Cursor;
60///     let mut buff = Cursor::new(vec![0; 15]);
61///
62///     write_ten_bytes_at_end(&mut buff).unwrap();
63///
64///     assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
65/// }
66/// ```
67#[derive(Clone, Debug, Default, Eq, PartialEq)]
68pub struct Cursor<T> {
69    inner: T,
70    pos: u64,
71}
72
73impl<T> Cursor<T> {
74    /// Creates a new cursor wrapping the provided underlying in-memory buffer.
75    ///
76    /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`])
77    /// is not empty. So writing to cursor starts with overwriting [`Vec`]
78    /// content, not with appending to it.
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use core2::io::Cursor;
84    ///
85    /// let buff = Cursor::new(Vec::new());
86    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
87    /// # force_inference(&buff);
88    /// ```
89    pub fn new(inner: T) -> Cursor<T> {
90        Cursor { pos: 0, inner }
91    }
92
93    /// Consumes this cursor, returning the underlying value.
94    ///
95    /// # Examples
96    ///
97    /// ```
98    /// use core2::io::Cursor;
99    ///
100    /// let buff = Cursor::new(Vec::new());
101    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
102    /// # force_inference(&buff);
103    ///
104    /// let vec = buff.into_inner();
105    /// ```
106    pub fn into_inner(self) -> T {
107        self.inner
108    }
109
110    /// Gets a reference to the underlying value in this cursor.
111    ///
112    /// # Examples
113    ///
114    /// ```
115    /// use core2::io::Cursor;
116    ///
117    /// let buff = Cursor::new(Vec::new());
118    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
119    /// # force_inference(&buff);
120    ///
121    /// let reference = buff.get_ref();
122    /// ```
123    pub fn get_ref(&self) -> &T {
124        &self.inner
125    }
126
127    /// Gets a mutable reference to the underlying value in this cursor.
128    ///
129    /// Care should be taken to avoid modifying the internal I/O state of the
130    /// underlying value as it may corrupt this cursor's position.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// use core2::io::Cursor;
136    ///
137    /// let mut buff = Cursor::new(Vec::new());
138    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
139    /// # force_inference(&buff);
140    ///
141    /// let reference = buff.get_mut();
142    /// ```
143    pub fn get_mut(&mut self) -> &mut T {
144        &mut self.inner
145    }
146
147    /// Returns the current position of this cursor.
148    ///
149    /// # Examples
150    ///
151    /// ```
152    /// use core2::io::{Cursor, Seek, SeekFrom};
153    /// use std::io::prelude::*;
154    ///
155    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
156    ///
157    /// assert_eq!(buff.position(), 0);
158    ///
159    /// buff.seek(SeekFrom::Current(2)).unwrap();
160    /// assert_eq!(buff.position(), 2);
161    ///
162    /// buff.seek(SeekFrom::Current(-1)).unwrap();
163    /// assert_eq!(buff.position(), 1);
164    /// ```
165    pub fn position(&self) -> u64 {
166        self.pos
167    }
168
169    /// Sets the position of this cursor.
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// use core2::io::Cursor;
175    ///
176    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
177    ///
178    /// assert_eq!(buff.position(), 0);
179    ///
180    /// buff.set_position(2);
181    /// assert_eq!(buff.position(), 2);
182    ///
183    /// buff.set_position(4);
184    /// assert_eq!(buff.position(), 4);
185    /// ```
186    pub fn set_position(&mut self, pos: u64) {
187        self.pos = pos;
188    }
189}
190
191impl<T> Seek for Cursor<T>
192where
193    T: AsRef<[u8]>,
194{
195    fn seek(&mut self, style: SeekFrom) -> Result<u64> {
196        let (base_pos, offset) = match style {
197            SeekFrom::Start(n) => {
198                self.pos = n;
199                return Ok(n);
200            }
201            SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
202            SeekFrom::Current(n) => (self.pos, n),
203        };
204        let new_pos = if offset >= 0 {
205            base_pos.checked_add(offset as u64)
206        } else {
207            base_pos.checked_sub((offset.wrapping_neg()) as u64)
208        };
209        match new_pos {
210            Some(n) => {
211                self.pos = n;
212                Ok(self.pos)
213            }
214            None => Err(Error::new(
215                ErrorKind::InvalidInput,
216                "invalid seek to a negative or overflowing position",
217            )),
218        }
219    }
220}
221
222impl<T> Read for Cursor<T>
223where
224    T: AsRef<[u8]>,
225{
226    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
227        let n = Read::read(&mut self.fill_buf()?, buf)?;
228        self.pos += n as u64;
229        Ok(n)
230    }
231
232    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
233        let n = buf.len();
234        Read::read_exact(&mut self.fill_buf()?, buf)?;
235        self.pos += n as u64;
236        Ok(())
237    }
238}
239
240impl<T> BufRead for Cursor<T>
241where
242    T: AsRef<[u8]>,
243{
244    fn fill_buf(&mut self) -> Result<&[u8]> {
245        let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
246        Ok(&self.inner.as_ref()[(amt as usize)..])
247    }
248    fn consume(&mut self, amt: usize) {
249        self.pos += amt as u64;
250    }
251}
252
253// Non-resizing write implementation
254#[inline]
255fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> Result<usize> {
256    let pos = cmp::min(*pos_mut, slice.len() as u64);
257    let amt = (&mut slice[(pos as usize)..]).write(buf)?;
258    *pos_mut += amt as u64;
259    Ok(amt)
260}
261
262impl Write for Cursor<&mut [u8]> {
263    #[inline]
264    fn write(&mut self, buf: &[u8]) -> Result<usize> {
265        slice_write(&mut self.pos, self.inner, buf)
266    }
267
268    #[inline]
269    fn flush(&mut self) -> Result<()> {
270        Ok(())
271    }
272}