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}