aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/io/cursor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ctr-std/src/io/cursor.rs')
-rw-r--r--ctr-std/src/io/cursor.rs197
1 files changed, 148 insertions, 49 deletions
diff --git a/ctr-std/src/io/cursor.rs b/ctr-std/src/io/cursor.rs
index 1b50233..c844770 100644
--- a/ctr-std/src/io/cursor.rs
+++ b/ctr-std/src/io/cursor.rs
@@ -12,7 +12,7 @@ use io::prelude::*;
use core::convert::TryInto;
use cmp;
-use io::{self, SeekFrom, Error, ErrorKind};
+use io::{self, Initializer, SeekFrom, Error, ErrorKind};
/// A `Cursor` wraps another type and provides it with a
/// [`Seek`] implementation.
@@ -45,10 +45,10 @@ use io::{self, SeekFrom, Error, ErrorKind};
///
/// // a library function we've written
/// fn write_ten_bytes_at_end<W: Write + Seek>(writer: &mut W) -> io::Result<()> {
-/// try!(writer.seek(SeekFrom::End(-10)));
+/// writer.seek(SeekFrom::End(-10))?;
///
/// for i in 0..10 {
-/// try!(writer.write(&[i]));
+/// writer.write(&[i])?;
/// }
///
/// // all went well
@@ -60,16 +60,16 @@ use io::{self, SeekFrom, Error, ErrorKind};
/// //
/// // We might want to use a BufReader here for efficiency, but let's
/// // keep this example focused.
-/// let mut file = try!(File::create("foo.txt"));
+/// let mut file = File::create("foo.txt")?;
///
-/// try!(write_ten_bytes_at_end(&mut file));
+/// write_ten_bytes_at_end(&mut file)?;
/// # Ok(())
/// # }
///
/// // now let's write a test
/// #[test]
/// fn test_writes_bytes() {
-/// // setting up a real File is much more slow than an in-memory buffer,
+/// // setting up a real File is much slower than an in-memory buffer,
/// // let's use a cursor instead
/// use std::io::Cursor;
/// let mut buff = Cursor::new(vec![0; 15]);
@@ -89,6 +89,10 @@ pub struct Cursor<T> {
impl<T> Cursor<T> {
/// Creates a new cursor wrapping the provided underlying I/O object.
///
+ /// Cursor initial position is `0` even if underlying object (e.
+ /// g. `Vec`) is not empty. So writing to cursor starts with
+ /// overwriting `Vec` content, not with appending to it.
+ ///
/// # Examples
///
/// ```
@@ -200,18 +204,20 @@ impl<T> Cursor<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
- let pos = match style {
- SeekFrom::Start(n) => { self.pos = n; return Ok(n) }
- SeekFrom::End(n) => self.inner.as_ref().len() as i64 + n,
- SeekFrom::Current(n) => self.pos as i64 + n,
+ let (base_pos, offset) = match style {
+ SeekFrom::Start(n) => { self.pos = n; return Ok(n); }
+ SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n),
+ SeekFrom::Current(n) => (self.pos, n),
};
-
- if pos < 0 {
- Err(Error::new(ErrorKind::InvalidInput,
- "invalid seek to a negative position"))
+ let new_pos = if offset >= 0 {
+ base_pos.checked_add(offset as u64)
} else {
- self.pos = pos as u64;
- Ok(self.pos)
+ base_pos.checked_sub((offset.wrapping_neg()) as u64)
+ };
+ match new_pos {
+ Some(n) => {self.pos = n; Ok(self.pos)}
+ None => Err(Error::new(ErrorKind::InvalidInput,
+ "invalid seek to a negative or overflowing position"))
}
}
}
@@ -223,6 +229,18 @@ impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
self.pos += n as u64;
Ok(n)
}
+
+ fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
+ let n = buf.len();
+ Read::read_exact(&mut self.fill_buf()?, buf)?;
+ self.pos += n as u64;
+ Ok(())
+ }
+
+ #[inline]
+ unsafe fn initializer(&self) -> Initializer {
+ Initializer::nop()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -234,14 +252,54 @@ impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> {
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
}
+// Non-resizing write implementation
+fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> {
+ let pos = cmp::min(*pos_mut, slice.len() as u64);
+ let amt = (&mut slice[(pos as usize)..]).write(buf)?;
+ *pos_mut += amt as u64;
+ Ok(amt)
+}
+
+// Resizing write implementation
+fn vec_write(pos_mut: &mut u64, vec: &mut Vec<u8>, buf: &[u8]) -> io::Result<usize> {
+ let pos: usize = (*pos_mut).try_into().map_err(|_| {
+ Error::new(ErrorKind::InvalidInput,
+ "cursor position exceeds maximum possible vector length")
+ })?;
+ // Make sure the internal buffer is as least as big as where we
+ // currently are
+ let len = vec.len();
+ if len < pos {
+ // use `resize` so that the zero filling is as efficient as possible
+ vec.resize(pos, 0);
+ }
+ // Figure out what bytes will be used to overwrite what's currently
+ // there (left), and what will be appended on the end (right)
+ {
+ let space = vec.len() - pos;
+ let (left, right) = buf.split_at(cmp::min(space, buf.len()));
+ vec[pos..pos + left.len()].copy_from_slice(left);
+ vec.extend_from_slice(right);
+ }
+
+ // Bump us forward
+ *pos_mut = (pos + buf.len()) as u64;
+ Ok(buf.len())
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> {
#[inline]
- fn write(&mut self, data: &[u8]) -> io::Result<usize> {
- let pos = cmp::min(self.pos, self.inner.len() as u64);
- let amt = (&mut self.inner[(pos as usize)..]).write(data)?;
- self.pos += amt as u64;
- Ok(amt)
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ slice_write(&mut self.pos, self.inner, buf)
+ }
+ fn flush(&mut self) -> io::Result<()> { Ok(()) }
+}
+
+#[unstable(feature = "cursor_mut_vec", issue = "30132")]
+impl<'a> Write for Cursor<&'a mut Vec<u8>> {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ vec_write(&mut self.pos, self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@@ -249,29 +307,7 @@ impl<'a> Write for Cursor<&'a mut [u8]> {
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Cursor<Vec<u8>> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let pos: usize = self.position().try_into().map_err(|_| {
- Error::new(ErrorKind::InvalidInput,
- "cursor position exceeds maximum possible vector length")
- })?;
- // Make sure the internal buffer is as least as big as where we
- // currently are
- let len = self.inner.len();
- if len < pos {
- // use `resize` so that the zero filling is as efficient as possible
- self.inner.resize(pos, 0);
- }
- // Figure out what bytes will be used to overwrite what's currently
- // there (left), and what will be appended on the end (right)
- {
- let space = self.inner.len() - pos;
- let (left, right) = buf.split_at(cmp::min(space, buf.len()));
- self.inner[pos..pos + left.len()].copy_from_slice(left);
- self.inner.extend_from_slice(right);
- }
-
- // Bump us forward
- self.set_position((pos + buf.len()) as u64);
- Ok(buf.len())
+ vec_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@@ -280,10 +316,7 @@ impl Write for Cursor<Vec<u8>> {
impl Write for Cursor<Box<[u8]>> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let pos = cmp::min(self.pos, self.inner.len() as u64);
- let amt = (&mut self.inner[(pos as usize)..]).write(buf)?;
- self.pos += amt as u64;
- Ok(amt)
+ slice_write(&mut self.pos, &mut self.inner, buf)
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@@ -314,6 +347,17 @@ mod tests {
}
#[test]
+ fn test_mem_mut_writer() {
+ let mut vec = Vec::new();
+ let mut writer = Cursor::new(&mut vec);
+ assert_eq!(writer.write(&[0]).unwrap(), 1);
+ assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+ assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+ let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
+ assert_eq!(&writer.get_ref()[..], b);
+ }
+
+ #[test]
fn test_box_slice_writer() {
let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
assert_eq!(writer.position(), 0);
@@ -445,7 +489,7 @@ mod tests {
#[test]
fn test_slice_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
- let mut reader = &mut &in_buf[..];
+ let reader = &mut &in_buf[..];
let mut buf = [];
assert_eq!(reader.read(&mut buf).unwrap(), 0);
let mut buf = [0];
@@ -465,6 +509,24 @@ mod tests {
}
#[test]
+ fn test_read_exact() {
+ let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+ let reader = &mut &in_buf[..];
+ let mut buf = [];
+ assert!(reader.read_exact(&mut buf).is_ok());
+ let mut buf = [8];
+ assert!(reader.read_exact(&mut buf).is_ok());
+ assert_eq!(buf[0], 0);
+ assert_eq!(reader.len(), 7);
+ let mut buf = [0, 0, 0, 0, 0, 0, 0];
+ assert!(reader.read_exact(&mut buf).is_ok());
+ assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]);
+ assert_eq!(reader.len(), 0);
+ let mut buf = [0];
+ assert!(reader.read_exact(&mut buf).is_err());
+ }
+
+ #[test]
fn test_buf_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
let mut reader = Cursor::new(&in_buf[..]);
@@ -527,6 +589,43 @@ mod tests {
}
#[test]
+ fn seek_past_i64() {
+ let buf = [0xff];
+ let mut r = Cursor::new(&buf[..]);
+ assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+ assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+ assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+ assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+ assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+ assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+
+ let mut r = Cursor::new(vec![10]);
+ assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+ assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+ assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+ assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+ assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+ assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+
+ let mut buf = [0];
+ let mut r = Cursor::new(&mut buf[..]);
+ assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+ assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+ assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+ assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+ assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+ assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+
+ let mut r = Cursor::new(vec![10].into_boxed_slice());
+ assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+ assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+ assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+ assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+ assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+ assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+ }
+
+ #[test]
fn seek_before_0() {
let buf = [0xff];
let mut r = Cursor::new(&buf[..]);