Skip to main content

bare_io/
cursor.rs

1use crate::{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/// ```no_run
26/// use std::io::prelude::*;
27/// use std::io::{self, SeekFrom};
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/// # fn foo() -> io::Result<()> {
43/// // Here's some code that uses this library function.
44/// //
45/// // We might want to use a BufReader here for efficiency, but let's
46/// // keep this example focused.
47/// let mut file = File::create("foo.txt")?;
48///
49/// write_ten_bytes_at_end(&mut file)?;
50/// # Ok(())
51/// # }
52///
53/// // now let's write a test
54/// #[test]
55/// fn test_writes_bytes() {
56///     // setting up a real File is much slower than an in-memory buffer,
57///     // let's use a cursor instead
58///     use std::io::Cursor;
59///     let mut buff = Cursor::new(vec![0; 15]);
60///
61///     write_ten_bytes_at_end(&mut buff).unwrap();
62///
63///     assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
64/// }
65/// ```
66#[derive(Clone, Debug, Default, Eq, PartialEq)]
67pub struct Cursor<T> {
68    inner: T,
69    pos: u64,
70}
71
72impl<T> Cursor<T> {
73    /// Creates a new cursor wrapping the provided underlying in-memory buffer.
74    ///
75    /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`])
76    /// is not empty. So writing to cursor starts with overwriting [`Vec`]
77    /// content, not with appending to it.
78    ///
79    /// # Examples
80    ///
81    /// ```
82    /// use std::io::Cursor;
83    ///
84    /// let buff = Cursor::new(Vec::new());
85    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
86    /// # force_inference(&buff);
87    /// ```
88    pub fn new(inner: T) -> Cursor<T> {
89        Cursor { pos: 0, inner }
90    }
91
92    /// Consumes this cursor, returning the underlying value.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use std::io::Cursor;
98    ///
99    /// let buff = Cursor::new(Vec::new());
100    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
101    /// # force_inference(&buff);
102    ///
103    /// let vec = buff.into_inner();
104    /// ```
105    pub fn into_inner(self) -> T {
106        self.inner
107    }
108
109    /// Gets a reference to the underlying value in this cursor.
110    ///
111    /// # Examples
112    ///
113    /// ```
114    /// use std::io::Cursor;
115    ///
116    /// let buff = Cursor::new(Vec::new());
117    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
118    /// # force_inference(&buff);
119    ///
120    /// let reference = buff.get_ref();
121    /// ```
122    pub fn get_ref(&self) -> &T {
123        &self.inner
124    }
125
126    /// Gets a mutable reference to the underlying value in this cursor.
127    ///
128    /// Care should be taken to avoid modifying the internal I/O state of the
129    /// underlying value as it may corrupt this cursor's position.
130    ///
131    /// # Examples
132    ///
133    /// ```
134    /// use std::io::Cursor;
135    ///
136    /// let mut buff = Cursor::new(Vec::new());
137    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
138    /// # force_inference(&buff);
139    ///
140    /// let reference = buff.get_mut();
141    /// ```
142    pub fn get_mut(&mut self) -> &mut T {
143        &mut self.inner
144    }
145
146    /// Returns the current position of this cursor.
147    ///
148    /// # Examples
149    ///
150    /// ```
151    /// use std::io::Cursor;
152    /// use std::io::prelude::*;
153    /// use std::io::SeekFrom;
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 std::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}