portable_io/
cursor.rs

1#[cfg(test)]
2mod tests;
3
4use core::cmp;
5use core::convert::TryInto;
6
7extern crate alloc;
8use alloc::boxed::Box;
9use alloc::vec::Vec;
10
11use crate::prelude::*;
12use crate::{self as io, Error, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
13
14/// A `Cursor` wraps an in-memory buffer and provides it with a
15/// [`Seek`] implementation.
16///
17/// `Cursor`s are used with in-memory buffers, anything implementing
18/// <code>[AsRef]<\[u8]></code>, to allow them to implement [`Read`] and/or [`Write`],
19/// allowing these buffers to be used anywhere you might use a reader or writer
20/// that does actual I/O.
21///
22/// The standard library implements some I/O traits on various types which
23/// are commonly used as a buffer, like <code>Cursor<[Vec]\<u8>></code> and
24/// <code>Cursor<[&\[u8\]][bytes]></code>.
25///
26/// <!-- TODO ADD EXAMPLE CODE THAT DOES NOT USE FS -->
27#[derive(Debug, Default, Eq, PartialEq)]
28pub struct Cursor<T> {
29    inner: T,
30    pos: u64,
31}
32
33impl<T> Cursor<T> {
34    /// Creates a new cursor wrapping the provided underlying in-memory buffer.
35    ///
36    /// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`])
37    /// is not empty. So writing to cursor starts with overwriting [`Vec`]
38    /// content, not with appending to it.
39    ///
40    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
41    /// # Example code
42    ///
43    /// ```
44    /// use portable_io::Cursor;
45    ///
46    /// let buff = Cursor::new(Vec::new());
47    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
48    /// # force_inference(&buff);
49    /// ```
50    pub const fn new(inner: T) -> Cursor<T> {
51        Cursor { pos: 0, inner }
52    }
53
54    /// Consumes this cursor, returning the underlying value.
55    ///
56    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
57    /// # Example code
58    ///
59    /// ```
60    /// use portable_io::Cursor;
61    ///
62    /// let buff = Cursor::new(Vec::new());
63    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
64    /// # force_inference(&buff);
65    ///
66    /// let vec = buff.into_inner();
67    /// ```
68    pub fn into_inner(self) -> T {
69        self.inner
70    }
71
72    /// Gets a reference to the underlying value in this cursor.
73    ///
74    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
75    /// # Example code
76    ///
77    /// ```
78    /// use portable_io::Cursor;
79    ///
80    /// let buff = Cursor::new(Vec::new());
81    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
82    /// # force_inference(&buff);
83    ///
84    /// let reference = buff.get_ref();
85    /// ```
86    pub const fn get_ref(&self) -> &T {
87        &self.inner
88    }
89
90    /// Gets a mutable reference to the underlying value in this cursor.
91    ///
92    /// Care should be taken to avoid modifying the internal I/O state of the
93    /// underlying value as it may corrupt this cursor's position.
94    ///
95    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
96    /// # Example code
97    ///
98    /// ```
99    /// use portable_io::Cursor;
100    ///
101    /// let mut buff = Cursor::new(Vec::new());
102    /// # fn force_inference(_: &Cursor<Vec<u8>>) {}
103    /// # force_inference(&buff);
104    ///
105    /// let reference = buff.get_mut();
106    /// ```
107    pub fn get_mut(&mut self) -> &mut T {
108        &mut self.inner
109    }
110
111    /// Returns the current position of this cursor.
112    ///
113    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
114    /// # Example code
115    ///
116    /// ```
117    /// use portable_io::prelude::*;
118    /// use portable_io::Cursor;
119    /// use portable_io::SeekFrom;
120    ///
121    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
122    ///
123    /// assert_eq!(buff.position(), 0);
124    ///
125    /// buff.seek(SeekFrom::Current(2)).unwrap();
126    /// assert_eq!(buff.position(), 2);
127    ///
128    /// buff.seek(SeekFrom::Current(-1)).unwrap();
129    /// assert_eq!(buff.position(), 1);
130    /// ```
131    pub const fn position(&self) -> u64 {
132        self.pos
133    }
134
135    /// Sets the position of this cursor.
136    ///
137    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
138    /// # Example code
139    ///
140    /// ```
141    /// use portable_io::Cursor;
142    ///
143    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
144    ///
145    /// assert_eq!(buff.position(), 0);
146    ///
147    /// buff.set_position(2);
148    /// assert_eq!(buff.position(), 2);
149    ///
150    /// buff.set_position(4);
151    /// assert_eq!(buff.position(), 4);
152    /// ```
153    pub fn set_position(&mut self, pos: u64) {
154        self.pos = pos;
155    }
156}
157
158impl<T> Cursor<T>
159where
160    T: AsRef<[u8]>,
161{
162    /// Returns the remaining slice.
163    ///
164    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
165    /// # Example code
166    ///
167    /// ```
168    /// use portable_io::Cursor;
169    ///
170    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
171    ///
172    /// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]);
173    ///
174    /// buff.set_position(2);
175    /// assert_eq!(buff.remaining_slice(), &[3, 4, 5]);
176    ///
177    /// buff.set_position(4);
178    /// assert_eq!(buff.remaining_slice(), &[5]);
179    ///
180    /// buff.set_position(6);
181    /// assert_eq!(buff.remaining_slice(), &[]);
182    /// ```
183    pub fn remaining_slice(&self) -> &[u8] {
184        let len = self.pos.min(self.inner.as_ref().len() as u64);
185        &self.inner.as_ref()[(len as usize)..]
186    }
187
188    /// Returns `true` if the remaining slice is empty.
189    ///
190    /// <!-- UPDATED TITLE in this fork to avoid singular vs plural issue - TODO PROPOSE UPDATE IN UPSTREAM RUST -->
191    /// # Example code
192    ///
193    /// ```
194    /// use portable_io::Cursor;
195    ///
196    /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
197    ///
198    /// buff.set_position(2);
199    /// assert!(!buff.is_empty());
200    ///
201    /// buff.set_position(5);
202    /// assert!(buff.is_empty());
203    ///
204    /// buff.set_position(10);
205    /// assert!(buff.is_empty());
206    /// ```
207    pub fn is_empty(&self) -> bool {
208        self.pos >= self.inner.as_ref().len() as u64
209    }
210}
211
212impl<T> Clone for Cursor<T>
213where
214    T: Clone,
215{
216    #[inline]
217    fn clone(&self) -> Self {
218        Cursor { inner: self.inner.clone(), pos: self.pos }
219    }
220
221    #[inline]
222    fn clone_from(&mut self, other: &Self) {
223        self.inner.clone_from(&other.inner);
224        self.pos = other.pos;
225    }
226}
227
228impl<T> io::Seek for Cursor<T>
229where
230    T: AsRef<[u8]>,
231{
232    fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
233        let (base_pos, offset) = match style {
234            SeekFrom::Start(n) => {
235                self.pos = n;
236                return Ok(n);
237            }
238            SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
239            SeekFrom::Current(n) => (self.pos, n),
240        };
241        match base_pos.checked_add_signed(offset) {
242            Some(n) => {
243                self.pos = n;
244                Ok(self.pos)
245            }
246            None => Err(Error::new_const(
247                ErrorKind::InvalidInput,
248                &"invalid seek to a negative or overflowing position",
249            )),
250        }
251    }
252
253    fn stream_len(&mut self) -> io::Result<u64> {
254        Ok(self.inner.as_ref().len() as u64)
255    }
256
257    fn stream_position(&mut self) -> io::Result<u64> {
258        Ok(self.pos)
259    }
260}
261
262impl<T> Read for Cursor<T>
263where
264    T: AsRef<[u8]>,
265{
266    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
267        let n = Read::read(&mut self.remaining_slice(), buf)?;
268        self.pos += n as u64;
269        Ok(n)
270    }
271
272    fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
273        let prev_filled = buf.filled_len();
274
275        Read::read_buf(&mut self.fill_buf()?, buf)?;
276
277        self.pos += (buf.filled_len() - prev_filled) as u64;
278
279        Ok(())
280    }
281
282    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
283        let mut nread = 0;
284        for buf in bufs {
285            let n = self.read(buf)?;
286            nread += n;
287            if n < buf.len() {
288                break;
289            }
290        }
291        Ok(nread)
292    }
293
294    fn is_read_vectored(&self) -> bool {
295        true
296    }
297
298    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
299        let n = buf.len();
300        Read::read_exact(&mut self.remaining_slice(), buf)?;
301        self.pos += n as u64;
302        Ok(())
303    }
304}
305
306impl<T> BufRead for Cursor<T>
307where
308    T: AsRef<[u8]>,
309{
310    fn fill_buf(&mut self) -> io::Result<&[u8]> {
311        Ok(self.remaining_slice())
312    }
313    fn consume(&mut self, amt: usize) {
314        self.pos += amt as u64;
315    }
316}
317
318// Non-resizing write implementation
319#[inline]
320fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
321    let pos = cmp::min(*pos_mut, slice.len() as u64);
322    let amt = (&mut slice[(pos as usize)..]).write(buf)?;
323    *pos_mut += amt as u64;
324    Ok(amt)
325}
326
327#[inline]
328fn slice_write_vectored(
329    pos_mut: &mut u64,
330    slice: &mut [u8],
331    bufs: &[IoSlice<'_>],
332) -> io::Result<usize> {
333    let mut nwritten = 0;
334    for buf in bufs {
335        let n = slice_write(pos_mut, slice, buf)?;
336        nwritten += n;
337        if n < buf.len() {
338            break;
339        }
340    }
341    Ok(nwritten)
342}
343
344// Resizing write implementation
345fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
346    let pos: usize = (*pos_mut).try_into().map_err(|_| {
347        Error::new_const(
348            ErrorKind::InvalidInput,
349            &"cursor position exceeds maximum possible vector length",
350        )
351    })?;
352    // Make sure the internal buffer is as least as big as where we
353    // currently are
354    let len = vec.len();
355    if len < pos {
356        // use `resize` so that the zero filling is as efficient as possible
357        vec.resize(pos, 0);
358    }
359    // Figure out what bytes will be used to overwrite what's currently
360    // there (left), and what will be appended on the end (right)
361    {
362        let space = vec.len() - pos;
363        let (left, right) = buf.split_at(cmp::min(space, buf.len()));
364        vec[pos..pos + left.len()].copy_from_slice(left);
365        vec.extend_from_slice(right);
366    }
367
368    // Bump us forward
369    *pos_mut = (pos + buf.len()) as u64;
370    Ok(buf.len())
371}
372
373fn vec_write_vectored(
374    pos_mut: &mut u64,
375    vec: &mut Vec<u8>,
376    bufs: &[IoSlice<'_>],
377) -> io::Result<usize> {
378    let mut nwritten = 0;
379    for buf in bufs {
380        nwritten += vec_write(pos_mut, vec, buf)?;
381    }
382    Ok(nwritten)
383}
384
385impl Write for Cursor<&mut [u8]> {
386    #[inline]
387    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
388        slice_write(&mut self.pos, self.inner, buf)
389    }
390
391    #[inline]
392    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
393        slice_write_vectored(&mut self.pos, self.inner, bufs)
394    }
395
396    #[inline]
397    fn is_write_vectored(&self) -> bool {
398        true
399    }
400
401    #[inline]
402    fn flush(&mut self) -> io::Result<()> {
403        Ok(())
404    }
405}
406
407impl Write for Cursor<&mut Vec<u8>> {
408    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
409        vec_write(&mut self.pos, self.inner, buf)
410    }
411
412    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
413        vec_write_vectored(&mut self.pos, self.inner, bufs)
414    }
415
416    #[inline]
417    fn is_write_vectored(&self) -> bool {
418        true
419    }
420
421    #[inline]
422    fn flush(&mut self) -> io::Result<()> {
423        Ok(())
424    }
425}
426
427impl Write for Cursor<Vec<u8>> {
428    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
429        vec_write(&mut self.pos, &mut self.inner, buf)
430    }
431
432    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
433        vec_write_vectored(&mut self.pos, &mut self.inner, bufs)
434    }
435
436    #[inline]
437    fn is_write_vectored(&self) -> bool {
438        true
439    }
440
441    #[inline]
442    fn flush(&mut self) -> io::Result<()> {
443        Ok(())
444    }
445}
446
447impl Write for Cursor<Box<[u8]>> {
448    #[inline]
449    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
450        slice_write(&mut self.pos, &mut self.inner, buf)
451    }
452
453    #[inline]
454    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
455        slice_write_vectored(&mut self.pos, &mut self.inner, bufs)
456    }
457
458    #[inline]
459    fn is_write_vectored(&self) -> bool {
460        true
461    }
462
463    #[inline]
464    fn flush(&mut self) -> io::Result<()> {
465        Ok(())
466    }
467}