From 1c7e1dd6453ebeab68aea35daa6a07e96a331af6 Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 20 Sep 2016 08:28:00 +0000 Subject: [PATCH] Rust: import core_io crate into libstd_artiq. Unfortunately the crate does not work out of the box with custom Rust builds, and forking it makes little sense over just embedding it here. See https://github.com/jethrogb/rust-core_io/issues/2. --- artiq/runtime.rs/libstd_artiq/io/buffered.rs | 1106 +++++++++++ artiq/runtime.rs/libstd_artiq/io/cursor.rs | 572 ++++++ artiq/runtime.rs/libstd_artiq/io/error.rs | 309 +++ artiq/runtime.rs/libstd_artiq/io/impls.rs | 289 +++ artiq/runtime.rs/libstd_artiq/io/memchr.rs | 297 +++ artiq/runtime.rs/libstd_artiq/io/mod.rs | 1845 ++++++++++++++++++ artiq/runtime.rs/libstd_artiq/io/prelude.rs | 25 + artiq/runtime.rs/libstd_artiq/io/util.rs | 208 ++ artiq/runtime.rs/libstd_artiq/lib.rs | 8 +- 9 files changed, 4658 insertions(+), 1 deletion(-) create mode 100644 artiq/runtime.rs/libstd_artiq/io/buffered.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/cursor.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/error.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/impls.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/memchr.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/mod.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/prelude.rs create mode 100644 artiq/runtime.rs/libstd_artiq/io/util.rs diff --git a/artiq/runtime.rs/libstd_artiq/io/buffered.rs b/artiq/runtime.rs/libstd_artiq/io/buffered.rs new file mode 100644 index 000000000..e23b74ff1 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/buffered.rs @@ -0,0 +1,1106 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Buffering wrappers for I/O traits + +use core::prelude::v1::*; +use io::prelude::*; + +use core::cmp; +use core::fmt; +use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind, SeekFrom}; +use io::memchr; + +/// The `BufReader` struct adds buffering to any reader. +/// +/// It can be excessively inefficient to work directly with a `Read` instance. +/// For example, every call to `read` on `TcpStream` results in a system call. +/// A `BufReader` performs large, infrequent reads on the underlying `Read` +/// and maintains an in-memory buffer of the results. +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io::BufReader; +/// use std::fs::File; +/// +/// # fn foo() -> std::io::Result<()> { +/// let mut f = try!(File::open("log.txt")); +/// let mut reader = BufReader::new(f); +/// +/// let mut line = String::new(); +/// let len = try!(reader.read_line(&mut line)); +/// println!("First line is {} bytes long", len); +/// # Ok(()) +/// # } +/// ``` +pub struct BufReader { + inner: R, + buf: Box<[u8]>, + pos: usize, + cap: usize, +} + +impl BufReader { + /// Creates a new `BufReader` with a default buffer capacity. + /// + /// # Examples + /// + /// ``` + /// use std::io::BufReader; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::open("log.txt")); + /// let mut reader = BufReader::new(f); + /// # Ok(()) + /// # } + /// ``` + pub fn new(inner: R) -> BufReader { + BufReader::with_capacity(DEFAULT_BUF_SIZE, inner) + } + + /// Creates a new `BufReader` with the specified buffer capacity. + /// + /// # Examples + /// + /// Creating a buffer with ten bytes of capacity: + /// + /// ``` + /// use std::io::BufReader; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f = try!(File::open("log.txt")); + /// let mut reader = BufReader::with_capacity(10, f); + /// # Ok(()) + /// # } + /// ``` + pub fn with_capacity(cap: usize, inner: R) -> BufReader { + BufReader { + inner: inner, + buf: vec![0; cap].into_boxed_slice(), + pos: 0, + cap: 0, + } + } + + /// Gets a reference to the underlying reader. + /// + /// It is inadvisable to directly read from the underlying reader. + /// + /// # Examples + /// + /// ``` + /// use std::io::BufReader; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f1 = try!(File::open("log.txt")); + /// let mut reader = BufReader::new(f1); + /// + /// let f2 = reader.get_ref(); + /// # Ok(()) + /// # } + /// ``` + pub fn get_ref(&self) -> &R { &self.inner } + + /// Gets a mutable reference to the underlying reader. + /// + /// It is inadvisable to directly read from the underlying reader. + /// + /// # Examples + /// + /// ``` + /// use std::io::BufReader; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f1 = try!(File::open("log.txt")); + /// let mut reader = BufReader::new(f1); + /// + /// let f2 = reader.get_mut(); + /// # Ok(()) + /// # } + /// ``` + pub fn get_mut(&mut self) -> &mut R { &mut self.inner } + + /// Unwraps this `BufReader`, returning the underlying reader. + /// + /// Note that any leftover data in the internal buffer is lost. + /// + /// # Examples + /// + /// ``` + /// use std::io::BufReader; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut f1 = try!(File::open("log.txt")); + /// let mut reader = BufReader::new(f1); + /// + /// let f2 = reader.into_inner(); + /// # Ok(()) + /// # } + /// ``` + pub fn into_inner(self) -> R { self.inner } +} + +impl Read for BufReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= self.buf.len() { + return self.inner.read(buf); + } + let nread = { + let mut rem = self.fill_buf()?; + rem.read(buf)? + }; + self.consume(nread); + Ok(nread) + } +} + +impl BufRead for BufReader { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + if self.pos == self.cap { + self.cap = self.inner.read(&mut self.buf)?; + self.pos = 0; + } + Ok(&self.buf[self.pos..self.cap]) + } + + fn consume(&mut self, amt: usize) { + self.pos = cmp::min(self.pos + amt, self.cap); + } +} + +impl fmt::Debug for BufReader where R: fmt::Debug { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BufReader") + .field("reader", &self.inner) + .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len())) + .finish() + } +} + +impl Seek for BufReader { + /// Seek to an offset, in bytes, in the underlying reader. + /// + /// The position used for seeking with `SeekFrom::Current(_)` is the + /// position the underlying reader would be at if the `BufReader` had no + /// internal buffer. + /// + /// Seeking always discards the internal buffer, even if the seek position + /// would otherwise fall within it. This guarantees that calling + /// `.unwrap()` immediately after a seek yields the underlying reader at + /// the same position. + /// + /// See `std::io::Seek` for more details. + /// + /// Note: In the edge case where you're seeking with `SeekFrom::Current(n)` + /// where `n` minus the internal buffer length underflows an `i64`, two + /// seeks will be performed instead of one. If the second seek returns + /// `Err`, the underlying reader will be left at the same position it would + /// have if you seeked to `SeekFrom::Current(0)`. + fn seek(&mut self, pos: SeekFrom) -> io::Result { + let result: u64; + if let SeekFrom::Current(n) = pos { + let remainder = (self.cap - self.pos) as i64; + // it should be safe to assume that remainder fits within an i64 as the alternative + // means we managed to allocate 8 ebibytes and that's absurd. + // But it's not out of the realm of possibility for some weird underlying reader to + // support seeking by i64::min_value() so we need to handle underflow when subtracting + // remainder. + if let Some(offset) = n.checked_sub(remainder) { + result = self.inner.seek(SeekFrom::Current(offset))?; + } else { + // seek backwards by our remainder, and then by the offset + self.inner.seek(SeekFrom::Current(-remainder))?; + self.pos = self.cap; // empty the buffer + result = self.inner.seek(SeekFrom::Current(n))?; + } + } else { + // Seeking with Start/End doesn't care about our buffer length. + result = self.inner.seek(pos)?; + } + self.pos = self.cap; // empty the buffer + Ok(result) + } +} + +/// Wraps a writer and buffers its output. +/// +/// It can be excessively inefficient to work directly with something that +/// implements `Write`. For example, every call to `write` on `TcpStream` +/// results in a system call. A `BufWriter` keeps an in-memory buffer of data +/// and writes it to an underlying writer in large, infrequent batches. +/// +/// The buffer will be written out when the writer is dropped. +/// +/// # Examples +/// +/// Let's write the numbers one through ten to a `TcpStream`: +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::net::TcpStream; +/// +/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); +/// +/// for i in 1..10 { +/// stream.write(&[i]).unwrap(); +/// } +/// ``` +/// +/// Because we're not buffering, we write each one in turn, incurring the +/// overhead of a system call per byte written. We can fix this with a +/// `BufWriter`: +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::io::BufWriter; +/// use std::net::TcpStream; +/// +/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); +/// +/// for i in 1..10 { +/// stream.write(&[i]).unwrap(); +/// } +/// ``` +/// +/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped +/// together by the buffer, and will all be written out in one system call when +/// the `stream` is dropped. +pub struct BufWriter { + inner: Option, + buf: Vec, + // #30888: If the inner writer panics in a call to write, we don't want to + // write the buffered data a second time in BufWriter's destructor. This + // flag tells the Drop impl if it should skip the flush. + panicked: bool, +} + +/// An error returned by `into_inner` which combines an error that +/// happened while writing out the buffer, and the buffered writer object +/// which may be used to recover from the condition. +/// +/// # Examples +/// +/// ```no_run +/// use std::io::BufWriter; +/// use std::net::TcpStream; +/// +/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); +/// +/// // do stuff with the stream +/// +/// // we want to get our `TcpStream` back, so let's try: +/// +/// let stream = match stream.into_inner() { +/// Ok(s) => s, +/// Err(e) => { +/// // Here, e is an IntoInnerError +/// panic!("An error occurred"); +/// } +/// }; +/// ``` +#[derive(Debug)] +pub struct IntoInnerError(W, Error); + +impl BufWriter { + /// Creates a new `BufWriter` with a default buffer capacity. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// ``` + pub fn new(inner: W) -> BufWriter { + BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) + } + + /// Creates a new `BufWriter` with the specified buffer capacity. + /// + /// # Examples + /// + /// Creating a buffer with a buffer of a hundred bytes. + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let stream = TcpStream::connect("127.0.0.1:34254").unwrap(); + /// let mut buffer = BufWriter::with_capacity(100, stream); + /// ``` + pub fn with_capacity(cap: usize, inner: W) -> BufWriter { + BufWriter { + inner: Some(inner), + buf: Vec::with_capacity(cap), + panicked: false, + } + } + + fn flush_buf(&mut self) -> io::Result<()> { + let mut written = 0; + let len = self.buf.len(); + let mut ret = Ok(()); + while written < len { + self.panicked = true; + let r = self.inner.as_mut().unwrap().write(&self.buf[written..]); + self.panicked = false; + + match r { + Ok(0) => { + ret = Err(Error::new(ErrorKind::WriteZero, + "failed to write the buffered data")); + break; + } + Ok(n) => written += n, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => { ret = Err(e); break } + + } + } + if written > 0 { + self.buf.drain(..written); + } + ret + } + + /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // we can use reference just like buffer + /// let reference = buffer.get_ref(); + /// ``` + pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } + + /// Gets a mutable reference to the underlying writer. + /// + /// It is inadvisable to directly write to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // we can use reference just like buffer + /// let reference = buffer.get_mut(); + /// ``` + pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } + + /// Unwraps this `BufWriter`, returning the underlying writer. + /// + /// The buffer is written out before returning the writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // unwrap the TcpStream and flush the buffer + /// let stream = buffer.into_inner().unwrap(); + /// ``` + pub fn into_inner(mut self) -> Result>> { + match self.flush_buf() { + Err(e) => Err(IntoInnerError(self, e)), + Ok(()) => Ok(self.inner.take().unwrap()) + } + } +} + +impl Write for BufWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + if self.buf.len() + buf.len() > self.buf.capacity() { + self.flush_buf()?; + } + if buf.len() >= self.buf.capacity() { + self.panicked = true; + let r = self.inner.as_mut().unwrap().write(buf); + self.panicked = false; + r + } else { + let amt = cmp::min(buf.len(), self.buf.capacity()); + Write::write(&mut self.buf, &buf[..amt]) + } + } + fn flush(&mut self) -> io::Result<()> { + self.flush_buf().and_then(|()| self.get_mut().flush()) + } +} + +impl fmt::Debug for BufWriter where W: fmt::Debug { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BufWriter") + .field("writer", &self.inner.as_ref().unwrap()) + .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) + .finish() + } +} + +impl Seek for BufWriter { + /// Seek to the offset, in bytes, in the underlying writer. + /// + /// Seeking always writes out the internal buffer before seeking. + fn seek(&mut self, pos: SeekFrom) -> io::Result { + self.flush_buf().and_then(|_| self.get_mut().seek(pos)) + } +} + +impl Drop for BufWriter { + fn drop(&mut self) { + if self.inner.is_some() && !self.panicked { + // dtors should not panic, so we ignore a failed flush + let _r = self.flush_buf(); + } + } +} + +impl IntoInnerError { + /// Returns the error which caused the call to `into_inner()` to fail. + /// + /// This error was returned when attempting to write the internal buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // do stuff with the stream + /// + /// // we want to get our `TcpStream` back, so let's try: + /// + /// let stream = match stream.into_inner() { + /// Ok(s) => s, + /// Err(e) => { + /// // Here, e is an IntoInnerError, let's log the inner error. + /// // + /// // We'll just 'log' to stdout for this example. + /// println!("{}", e.error()); + /// + /// panic!("An unexpected error occurred."); + /// } + /// }; + /// ``` + pub fn error(&self) -> &Error { &self.1 } + + /// Returns the buffered writer instance which generated the error. + /// + /// The returned object can be used for error recovery, such as + /// re-inspecting the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // do stuff with the stream + /// + /// // we want to get our `TcpStream` back, so let's try: + /// + /// let stream = match stream.into_inner() { + /// Ok(s) => s, + /// Err(e) => { + /// // Here, e is an IntoInnerError, let's re-examine the buffer: + /// let buffer = e.into_inner(); + /// + /// // do stuff to try to recover + /// + /// // afterwards, let's just return the stream + /// buffer.into_inner().unwrap() + /// } + /// }; + /// ``` + pub fn into_inner(self) -> W { self.0 } +} + +impl From> for Error { + fn from(iie: IntoInnerError) -> Error { iie.1 } +} + +impl fmt::Display for IntoInnerError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.error().fmt(f) + } +} + +/// Wraps a writer and buffers output to it, flushing whenever a newline +/// (`0x0a`, `'\n'`) is detected. +/// +/// The [`BufWriter`][bufwriter] struct wraps a writer and buffers its output. +/// But it only does this batched write when it goes out of scope, or when the +/// internal buffer is full. Sometimes, you'd prefer to write each line as it's +/// completed, rather than the entire buffer at once. Enter `LineWriter`. It +/// does exactly that. +/// +/// [bufwriter]: struct.BufWriter.html +/// +/// If there's still a partial line in the buffer when the `LineWriter` is +/// dropped, it will flush those contents. +/// +/// # Examples +/// +/// We can use `LineWriter` to write one line at a time, significantly +/// reducing the number of actual writes to the file. +/// +/// ``` +/// use std::fs::File; +/// use std::io::prelude::*; +/// use std::io::LineWriter; +/// +/// # fn foo() -> std::io::Result<()> { +/// let road_not_taken = b"I shall be telling this with a sigh +/// Somewhere ages and ages hence: +/// Two roads diverged in a wood, and I - +/// I took the one less traveled by, +/// And that has made all the difference."; +/// +/// let file = try!(File::create("poem.txt")); +/// let mut file = LineWriter::new(file); +/// +/// for &byte in road_not_taken.iter() { +/// file.write(&[byte]).unwrap(); +/// } +/// +/// // let's check we did the right thing. +/// let mut file = try!(File::open("poem.txt")); +/// let mut contents = String::new(); +/// +/// try!(file.read_to_string(&mut contents)); +/// +/// assert_eq!(contents.as_bytes(), &road_not_taken[..]); +/// # Ok(()) +/// # } +/// ``` +pub struct LineWriter { + inner: BufWriter, +} + +impl LineWriter { + /// Creates a new `LineWriter`. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let file = LineWriter::new(file); + /// # Ok(()) + /// # } + /// ``` + pub fn new(inner: W) -> LineWriter { + // Lines typically aren't that long, don't use a giant buffer + LineWriter::with_capacity(1024, inner) + } + + /// Creates a new `LineWriter` with a specified capacity for the internal + /// buffer. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let file = LineWriter::with_capacity(100, file); + /// # Ok(()) + /// # } + /// ``` + pub fn with_capacity(cap: usize, inner: W) -> LineWriter { + LineWriter { inner: BufWriter::with_capacity(cap, inner) } + } + + /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let file = LineWriter::new(file); + /// + /// let reference = file.get_ref(); + /// # Ok(()) + /// # } + /// ``` + pub fn get_ref(&self) -> &W { self.inner.get_ref() } + + /// Gets a mutable reference to the underlying writer. + /// + /// Caution must be taken when calling methods on the mutable reference + /// returned as extra writes could corrupt the output stream. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// let mut file = LineWriter::new(file); + /// + /// // we can use reference just like file + /// let reference = file.get_mut(); + /// # Ok(()) + /// # } + /// ``` + pub fn get_mut(&mut self) -> &mut W { self.inner.get_mut() } + + /// Unwraps this `LineWriter`, returning the underlying writer. + /// + /// The internal buffer is written out before returning the writer. + /// + /// # Examples + /// + /// ``` + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// # fn foo() -> std::io::Result<()> { + /// let file = try!(File::create("poem.txt")); + /// + /// let writer: LineWriter = LineWriter::new(file); + /// + /// let file: File = try!(writer.into_inner()); + /// # Ok(()) + /// # } + /// ``` + pub fn into_inner(self) -> Result>> { + self.inner.into_inner().map_err(|IntoInnerError(buf, e)| { + IntoInnerError(LineWriter { inner: buf }, e) + }) + } +} + +impl Write for LineWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + match memchr::memrchr(b'\n', buf) { + Some(i) => { + let n = self.inner.write(&buf[..i + 1])?; + if n != i + 1 || self.inner.flush().is_err() { + // Do not return errors on partial writes. + return Ok(n); + } + self.inner.write(&buf[i + 1..]).map(|i| n + i) + } + None => self.inner.write(buf), + } + } + + fn flush(&mut self) -> io::Result<()> { self.inner.flush() } +} + +impl fmt::Debug for LineWriter where W: fmt::Debug { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("LineWriter") + .field("writer", &self.inner.inner) + .field("buffer", + &format_args!("{}/{}", self.inner.buf.len(), self.inner.buf.capacity())) + .finish() + } +} + +#[cfg(test)] +mod tests { + use prelude::v1::*; + use io::prelude::*; + use io::{self, BufReader, BufWriter, LineWriter, SeekFrom}; + use sync::atomic::{AtomicUsize, Ordering}; + use thread; + use test; + + /// A dummy reader intended at testing short-reads propagation. + pub struct ShortReader { + lengths: Vec, + } + + impl Read for ShortReader { + fn read(&mut self, _: &mut [u8]) -> io::Result { + if self.lengths.is_empty() { + Ok(0) + } else { + Ok(self.lengths.remove(0)) + } + } + } + + #[test] + fn test_buffered_reader() { + let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; + let mut reader = BufReader::with_capacity(2, inner); + + let mut buf = [0, 0, 0]; + let nread = reader.read(&mut buf); + assert_eq!(nread.unwrap(), 3); + let b: &[_] = &[5, 6, 7]; + assert_eq!(buf, b); + + let mut buf = [0, 0]; + let nread = reader.read(&mut buf); + assert_eq!(nread.unwrap(), 2); + let b: &[_] = &[0, 1]; + assert_eq!(buf, b); + + let mut buf = [0]; + let nread = reader.read(&mut buf); + assert_eq!(nread.unwrap(), 1); + let b: &[_] = &[2]; + assert_eq!(buf, b); + + let mut buf = [0, 0, 0]; + let nread = reader.read(&mut buf); + assert_eq!(nread.unwrap(), 1); + let b: &[_] = &[3, 0, 0]; + assert_eq!(buf, b); + + let nread = reader.read(&mut buf); + assert_eq!(nread.unwrap(), 1); + let b: &[_] = &[4, 0, 0]; + assert_eq!(buf, b); + + assert_eq!(reader.read(&mut buf).unwrap(), 0); + } + + #[test] + fn test_buffered_reader_seek() { + let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; + let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner)); + + assert_eq!(reader.seek(SeekFrom::Start(3)).ok(), Some(3)); + assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); + assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(3)); + assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); + assert_eq!(reader.seek(SeekFrom::Current(1)).ok(), Some(4)); + assert_eq!(reader.fill_buf().ok(), Some(&[1, 2][..])); + reader.consume(1); + assert_eq!(reader.seek(SeekFrom::Current(-2)).ok(), Some(3)); + } + + #[test] + fn test_buffered_reader_seek_underflow() { + // gimmick reader that yields its position modulo 256 for each byte + struct PositionReader { + pos: u64 + } + impl Read for PositionReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = buf.len(); + for x in buf { + *x = self.pos as u8; + self.pos = self.pos.wrapping_add(1); + } + Ok(len) + } + } + impl Seek for PositionReader { + fn seek(&mut self, pos: SeekFrom) -> io::Result { + match pos { + SeekFrom::Start(n) => { + self.pos = n; + } + SeekFrom::Current(n) => { + self.pos = self.pos.wrapping_add(n as u64); + } + SeekFrom::End(n) => { + self.pos = u64::max_value().wrapping_add(n as u64); + } + } + Ok(self.pos) + } + } + + let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 }); + assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..])); + assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::max_value()-5)); + assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5)); + // the following seek will require two underlying seeks + let expected = 9223372036854775802; + assert_eq!(reader.seek(SeekFrom::Current(i64::min_value())).ok(), Some(expected)); + assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5)); + // seeking to 0 should empty the buffer. + assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(expected)); + assert_eq!(reader.get_ref().pos, expected); + } + + #[test] + fn test_buffered_writer() { + let inner = Vec::new(); + let mut writer = BufWriter::with_capacity(2, inner); + + writer.write(&[0, 1]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1]); + + writer.write(&[2]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1]); + + writer.write(&[3]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1]); + + writer.flush().unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); + + writer.write(&[4]).unwrap(); + writer.write(&[5]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); + + writer.write(&[6]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]); + + writer.write(&[7, 8]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]); + + writer.write(&[9, 10, 11]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + + writer.flush().unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + } + + #[test] + fn test_buffered_writer_inner_flushes() { + let mut w = BufWriter::with_capacity(3, Vec::new()); + w.write(&[0, 1]).unwrap(); + assert_eq!(*w.get_ref(), []); + let w = w.into_inner().unwrap(); + assert_eq!(w, [0, 1]); + } + + #[test] + fn test_buffered_writer_seek() { + let mut w = BufWriter::with_capacity(3, io::Cursor::new(Vec::new())); + w.write_all(&[0, 1, 2, 3, 4, 5]).unwrap(); + w.write_all(&[6, 7]).unwrap(); + assert_eq!(w.seek(SeekFrom::Current(0)).ok(), Some(8)); + assert_eq!(&w.get_ref().get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]); + assert_eq!(w.seek(SeekFrom::Start(2)).ok(), Some(2)); + w.write_all(&[8, 9]).unwrap(); + assert_eq!(&w.into_inner().unwrap().into_inner()[..], &[0, 1, 8, 9, 4, 5, 6, 7]); + } + + #[test] + fn test_read_until() { + let inner: &[u8] = &[0, 1, 2, 1, 0]; + let mut reader = BufReader::with_capacity(2, inner); + let mut v = Vec::new(); + reader.read_until(0, &mut v).unwrap(); + assert_eq!(v, [0]); + v.truncate(0); + reader.read_until(2, &mut v).unwrap(); + assert_eq!(v, [1, 2]); + v.truncate(0); + reader.read_until(1, &mut v).unwrap(); + assert_eq!(v, [1]); + v.truncate(0); + reader.read_until(8, &mut v).unwrap(); + assert_eq!(v, [0]); + v.truncate(0); + reader.read_until(9, &mut v).unwrap(); + assert_eq!(v, []); + } + + #[test] + fn test_line_buffer_fail_flush() { + // Issue #32085 + struct FailFlushWriter<'a>(&'a mut Vec); + + impl<'a> Write for FailFlushWriter<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.extend_from_slice(buf); + Ok(buf.len()) + } + fn flush(&mut self) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "flush failed")) + } + } + + let mut buf = Vec::new(); + { + let mut writer = LineWriter::new(FailFlushWriter(&mut buf)); + let to_write = b"abc\ndef"; + if let Ok(written) = writer.write(to_write) { + assert!(written < to_write.len(), "didn't flush on new line"); + // PASS + return; + } + } + assert!(buf.is_empty(), "write returned an error but wrote data"); + } + + #[test] + fn test_line_buffer() { + let mut writer = LineWriter::new(Vec::new()); + writer.write(&[0]).unwrap(); + assert_eq!(*writer.get_ref(), []); + writer.write(&[1]).unwrap(); + assert_eq!(*writer.get_ref(), []); + writer.flush().unwrap(); + assert_eq!(*writer.get_ref(), [0, 1]); + writer.write(&[0, b'\n', 1, b'\n', 2]).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n']); + writer.flush().unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2]); + writer.write(&[3, b'\n']).unwrap(); + assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']); + } + + #[test] + fn test_read_line() { + let in_buf: &[u8] = b"a\nb\nc"; + let mut reader = BufReader::with_capacity(2, in_buf); + let mut s = String::new(); + reader.read_line(&mut s).unwrap(); + assert_eq!(s, "a\n"); + s.truncate(0); + reader.read_line(&mut s).unwrap(); + assert_eq!(s, "b\n"); + s.truncate(0); + reader.read_line(&mut s).unwrap(); + assert_eq!(s, "c"); + s.truncate(0); + reader.read_line(&mut s).unwrap(); + assert_eq!(s, ""); + } + + #[test] + fn test_lines() { + let in_buf: &[u8] = b"a\nb\nc"; + let reader = BufReader::with_capacity(2, in_buf); + let mut it = reader.lines(); + assert_eq!(it.next().unwrap().unwrap(), "a".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "b".to_string()); + assert_eq!(it.next().unwrap().unwrap(), "c".to_string()); + assert!(it.next().is_none()); + } + + #[test] + fn test_short_reads() { + let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]}; + let mut reader = BufReader::new(inner); + let mut buf = [0, 0]; + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 2); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + } + + #[test] + fn read_char_buffered() { + let buf = [195, 159]; + let reader = BufReader::with_capacity(1, &buf[..]); + assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß'); + } + + #[test] + fn test_chars() { + let buf = [195, 159, b'a']; + let reader = BufReader::with_capacity(1, &buf[..]); + let mut it = reader.chars(); + assert_eq!(it.next().unwrap().unwrap(), 'ß'); + assert_eq!(it.next().unwrap().unwrap(), 'a'); + assert!(it.next().is_none()); + } + + #[test] + #[should_panic] + fn dont_panic_in_drop_on_panicked_flush() { + struct FailFlushWriter; + + impl Write for FailFlushWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { Ok(buf.len()) } + fn flush(&mut self) -> io::Result<()> { + Err(io::Error::last_os_error()) + } + } + + let writer = FailFlushWriter; + let _writer = BufWriter::new(writer); + + // If writer panics *again* due to the flush error then the process will + // abort. + panic!(); + } + + #[test] + fn panic_in_write_doesnt_flush_in_drop() { + static WRITES: AtomicUsize = AtomicUsize::new(0); + + struct PanicWriter; + + impl Write for PanicWriter { + fn write(&mut self, _: &[u8]) -> io::Result { + WRITES.fetch_add(1, Ordering::SeqCst); + panic!(); + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } + } + + thread::spawn(|| { + let mut writer = BufWriter::new(PanicWriter); + let _ = writer.write(b"hello world"); + let _ = writer.flush(); + }).join().unwrap_err(); + + assert_eq!(WRITES.load(Ordering::SeqCst), 1); + } + + #[bench] + fn bench_buffered_reader(b: &mut test::Bencher) { + b.iter(|| { + BufReader::new(io::empty()) + }); + } + + #[bench] + fn bench_buffered_writer(b: &mut test::Bencher) { + b.iter(|| { + BufWriter::new(io::sink()) + }); + } +} diff --git a/artiq/runtime.rs/libstd_artiq/io/cursor.rs b/artiq/runtime.rs/libstd_artiq/io/cursor.rs new file mode 100644 index 000000000..1db50ee5b --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/cursor.rs @@ -0,0 +1,572 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::v1::*; +use io::prelude::*; + +use core::cmp; +use io::{self, SeekFrom, Error, ErrorKind}; + +/// A `Cursor` wraps another type and provides it with a +/// [`Seek`](trait.Seek.html) implementation. +/// +/// Cursors are typically used with in-memory buffers to allow them to +/// implement `Read` and/or `Write`, allowing these buffers to be used +/// anywhere you might use a reader or writer that does actual I/O. +/// +/// The standard library implements some I/O traits on various types which +/// are commonly used as a buffer, like `Cursor>` and `Cursor<&[u8]>`. +/// +/// # Examples +/// +/// We may want to write bytes to a [`File`][file] in our production +/// code, but use an in-memory buffer in our tests. We can do this with +/// `Cursor`: +/// +/// [file]: ../fs/struct.File.html +/// +/// ```no_run +/// use std::io::prelude::*; +/// use std::io::{self, SeekFrom}; +/// use std::fs::File; +/// +/// // a library function we've written +/// fn write_ten_bytes_at_end(writer: &mut W) -> io::Result<()> { +/// try!(writer.seek(SeekFrom::End(-10))); +/// +/// for i in 0..10 { +/// try!(writer.write(&[i])); +/// } +/// +/// // all went well +/// Ok(()) +/// } +/// +/// # fn foo() -> io::Result<()> { +/// // Here's some code that uses this library function. +/// // +/// // 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")); +/// +/// try!(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, +/// // let's use a cursor instead +/// use std::io::Cursor; +/// let mut buff = Cursor::new(vec![0; 15]); +/// +/// write_ten_bytes_at_end(&mut buff).unwrap(); +/// +/// assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +/// } +/// ``` +#[derive(Clone, Debug)] +pub struct Cursor { + inner: T, + pos: u64, +} + +impl Cursor { + /// Creates a new cursor wrapping the provided underlying I/O object. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// ``` + pub fn new(inner: T) -> Cursor { + Cursor { pos: 0, inner: inner } + } + + /// Consumes this cursor, returning the underlying value. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let vec = buff.into_inner(); + /// ``` + pub fn into_inner(self) -> T { self.inner } + + /// Gets a reference to the underlying value in this cursor. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_ref(); + /// ``` + pub fn get_ref(&self) -> &T { &self.inner } + + /// Gets a mutable reference to the underlying value in this cursor. + /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying value as it may corrupt this cursor's position. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(Vec::new()); + /// # fn force_inference(_: &Cursor>) {} + /// # force_inference(&buff); + /// + /// let reference = buff.get_mut(); + /// ``` + pub fn get_mut(&mut self) -> &mut T { &mut self.inner } + + /// Returns the current position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// use std::io::prelude::*; + /// use std::io::SeekFrom; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.seek(SeekFrom::Current(2)).unwrap(); + /// assert_eq!(buff.position(), 2); + /// + /// buff.seek(SeekFrom::Current(-1)).unwrap(); + /// assert_eq!(buff.position(), 1); + /// ``` + pub fn position(&self) -> u64 { self.pos } + + /// Sets the position of this cursor. + /// + /// # Examples + /// + /// ``` + /// use std::io::Cursor; + /// + /// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]); + /// + /// assert_eq!(buff.position(), 0); + /// + /// buff.set_position(2); + /// assert_eq!(buff.position(), 2); + /// + /// buff.set_position(4); + /// assert_eq!(buff.position(), 4); + /// ``` + pub fn set_position(&mut self, pos: u64) { self.pos = pos; } +} + +impl io::Seek for Cursor where T: AsRef<[u8]> { + fn seek(&mut self, style: SeekFrom) -> io::Result { + 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, + }; + + if pos < 0 { + Err(Error::new(ErrorKind::InvalidInput, + "invalid seek to a negative position")) + } else { + self.pos = pos as u64; + Ok(self.pos) + } + } +} + +impl Read for Cursor where T: AsRef<[u8]> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let n = Read::read(&mut self.fill_buf()?, buf)?; + self.pos += n as u64; + Ok(n) + } +} + +impl BufRead for Cursor where T: AsRef<[u8]> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64); + Ok(&self.inner.as_ref()[(amt as usize)..]) + } + fn consume(&mut self, amt: usize) { self.pos += amt as u64; } +} + +impl<'a> Write for Cursor<&'a mut [u8]> { + #[inline] + fn write(&mut self, data: &[u8]) -> io::Result { + 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 flush(&mut self) -> io::Result<()> { Ok(()) } +} + +impl Write for Cursor> { + fn write(&mut self, buf: &[u8]) -> io::Result { + // Make sure the internal buffer is as least as big as where we + // currently are + let pos = self.position(); + let amt = pos.saturating_sub(self.inner.len() as u64); + // use `resize` so that the zero filling is as efficient as possible + let len = self.inner.len(); + self.inner.resize(len + amt as usize, 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 pos = pos as usize; + 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()) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +impl Write for Cursor> { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + 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) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(test)] +mod tests { + use io::prelude::*; + use io::{Cursor, SeekFrom}; + use vec::Vec; + + #[test] + fn test_vec_writer() { + let mut writer = Vec::new(); + 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, b); + } + + #[test] + fn test_mem_writer() { + let mut writer = Cursor::new(Vec::new()); + 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); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.position(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); + assert_eq!(writer.position(), 8); + assert_eq!(writer.write(&[]).unwrap(), 0); + assert_eq!(writer.position(), 8); + + assert_eq!(writer.write(&[8, 9]).unwrap(), 1); + assert_eq!(writer.write(&[10]).unwrap(), 0); + let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; + assert_eq!(&**writer.get_ref(), b); + } + + #[test] + fn test_buf_writer() { + let mut buf = [0 as u8; 9]; + { + let mut writer = Cursor::new(&mut buf[..]); + assert_eq!(writer.position(), 0); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.position(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); + assert_eq!(writer.position(), 8); + assert_eq!(writer.write(&[]).unwrap(), 0); + assert_eq!(writer.position(), 8); + + assert_eq!(writer.write(&[8, 9]).unwrap(), 1); + assert_eq!(writer.write(&[10]).unwrap(), 0); + } + let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; + assert_eq!(buf, b); + } + + #[test] + fn test_buf_writer_seek() { + let mut buf = [0 as u8; 8]; + { + let mut writer = Cursor::new(&mut buf[..]); + assert_eq!(writer.position(), 0); + assert_eq!(writer.write(&[1]).unwrap(), 1); + assert_eq!(writer.position(), 1); + + assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2); + assert_eq!(writer.position(), 2); + assert_eq!(writer.write(&[2]).unwrap(), 1); + assert_eq!(writer.position(), 3); + + assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1); + assert_eq!(writer.position(), 1); + assert_eq!(writer.write(&[3]).unwrap(), 1); + assert_eq!(writer.position(), 2); + + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); + assert_eq!(writer.position(), 7); + assert_eq!(writer.write(&[4]).unwrap(), 1); + assert_eq!(writer.position(), 8); + + } + let b: &[_] = &[1, 3, 2, 0, 0, 0, 0, 4]; + assert_eq!(buf, b); + } + + #[test] + fn test_buf_writer_error() { + let mut buf = [0 as u8; 2]; + let mut writer = Cursor::new(&mut buf[..]); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 1); + assert_eq!(writer.write(&[0, 0]).unwrap(), 0); + } + + #[test] + fn test_mem_reader() { + let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); + let mut buf = []; + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.position(), 0); + let mut buf = [0]; + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.position(), 1); + let b: &[_] = &[0]; + assert_eq!(buf, b); + let mut buf = [0; 4]; + assert_eq!(reader.read(&mut buf).unwrap(), 4); + assert_eq!(reader.position(), 5); + let b: &[_] = &[1, 2, 3, 4]; + assert_eq!(buf, b); + assert_eq!(reader.read(&mut buf).unwrap(), 3); + let b: &[_] = &[5, 6, 7]; + assert_eq!(&buf[..3], b); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + } + + #[test] + fn test_boxed_slice_reader() { + let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7).into_boxed_slice()); + let mut buf = []; + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.position(), 0); + let mut buf = [0]; + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.position(), 1); + let b: &[_] = &[0]; + assert_eq!(buf, b); + let mut buf = [0; 4]; + assert_eq!(reader.read(&mut buf).unwrap(), 4); + assert_eq!(reader.position(), 5); + let b: &[_] = &[1, 2, 3, 4]; + assert_eq!(buf, b); + assert_eq!(reader.read(&mut buf).unwrap(), 3); + let b: &[_] = &[5, 6, 7]; + assert_eq!(&buf[..3], b); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + } + + #[test] + fn read_to_end() { + let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7)); + let mut v = Vec::new(); + reader.read_to_end(&mut v).unwrap(); + assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]); + } + + #[test] + fn test_slice_reader() { + let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let mut reader = &mut &in_buf[..]; + let mut buf = []; + assert_eq!(reader.read(&mut buf).unwrap(), 0); + let mut buf = [0]; + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.len(), 7); + let b: &[_] = &[0]; + assert_eq!(&buf[..], b); + let mut buf = [0; 4]; + assert_eq!(reader.read(&mut buf).unwrap(), 4); + assert_eq!(reader.len(), 3); + let b: &[_] = &[1, 2, 3, 4]; + assert_eq!(&buf[..], b); + assert_eq!(reader.read(&mut buf).unwrap(), 3); + let b: &[_] = &[5, 6, 7]; + assert_eq!(&buf[..3], b); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + } + + #[test] + fn test_buf_reader() { + let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; + let mut reader = Cursor::new(&in_buf[..]); + let mut buf = []; + assert_eq!(reader.read(&mut buf).unwrap(), 0); + assert_eq!(reader.position(), 0); + let mut buf = [0]; + assert_eq!(reader.read(&mut buf).unwrap(), 1); + assert_eq!(reader.position(), 1); + let b: &[_] = &[0]; + assert_eq!(buf, b); + let mut buf = [0; 4]; + assert_eq!(reader.read(&mut buf).unwrap(), 4); + assert_eq!(reader.position(), 5); + let b: &[_] = &[1, 2, 3, 4]; + assert_eq!(buf, b); + assert_eq!(reader.read(&mut buf).unwrap(), 3); + let b: &[_] = &[5, 6, 7]; + assert_eq!(&buf[..3], b); + assert_eq!(reader.read(&mut buf).unwrap(), 0); + } + + #[test] + fn test_read_char() { + let b = &b"Vi\xE1\xBB\x87t"[..]; + let mut c = Cursor::new(b).chars(); + assert_eq!(c.next().unwrap().unwrap(), 'V'); + assert_eq!(c.next().unwrap().unwrap(), 'i'); + assert_eq!(c.next().unwrap().unwrap(), 'ệ'); + assert_eq!(c.next().unwrap().unwrap(), 't'); + assert!(c.next().is_none()); + } + + #[test] + fn test_read_bad_char() { + let b = &b"\x80"[..]; + let mut c = Cursor::new(b).chars(); + assert!(c.next().unwrap().is_err()); + } + + #[test] + fn seek_past_end() { + let buf = [0xff]; + let mut r = Cursor::new(&buf[..]); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); + + let mut r = Cursor::new(vec!(10)); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.read(&mut [0]).unwrap(), 0); + + let mut buf = [0]; + let mut r = Cursor::new(&mut buf[..]); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 0); + + let mut r = Cursor::new(vec![10].into_boxed_slice()); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 0); + } + + #[test] + fn seek_before_0() { + let buf = [0xff]; + let mut r = Cursor::new(&buf[..]); + assert!(r.seek(SeekFrom::End(-2)).is_err()); + + let mut r = Cursor::new(vec!(10)); + assert!(r.seek(SeekFrom::End(-2)).is_err()); + + let mut buf = [0]; + let mut r = Cursor::new(&mut buf[..]); + assert!(r.seek(SeekFrom::End(-2)).is_err()); + + let mut r = Cursor::new(vec!(10).into_boxed_slice()); + assert!(r.seek(SeekFrom::End(-2)).is_err()); + } + + #[test] + fn test_seekable_mem_writer() { + let mut writer = Cursor::new(Vec::::new()); + assert_eq!(writer.position(), 0); + assert_eq!(writer.write(&[0]).unwrap(), 1); + assert_eq!(writer.position(), 1); + assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3); + assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4); + assert_eq!(writer.position(), 8); + let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; + assert_eq!(&writer.get_ref()[..], b); + + assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0); + assert_eq!(writer.position(), 0); + assert_eq!(writer.write(&[3, 4]).unwrap(), 2); + let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; + assert_eq!(&writer.get_ref()[..], b); + + assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3); + assert_eq!(writer.write(&[0, 1]).unwrap(), 2); + let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; + assert_eq!(&writer.get_ref()[..], b); + + assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7); + assert_eq!(writer.write(&[1, 2]).unwrap(), 2); + let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; + assert_eq!(&writer.get_ref()[..], b); + + assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10); + assert_eq!(writer.write(&[1]).unwrap(), 1); + let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; + assert_eq!(&writer.get_ref()[..], b); + } + + #[test] + fn vec_seek_past_end() { + let mut r = Cursor::new(Vec::new()); + assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10); + assert_eq!(r.write(&[3]).unwrap(), 1); + } + + #[test] + fn vec_seek_before_0() { + let mut r = Cursor::new(Vec::new()); + assert!(r.seek(SeekFrom::End(-2)).is_err()); + } +} diff --git a/artiq/runtime.rs/libstd_artiq/io/error.rs b/artiq/runtime.rs/libstd_artiq/io/error.rs new file mode 100644 index 000000000..bdb040c03 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/error.rs @@ -0,0 +1,309 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use alloc::boxed::Box; +use core::convert::Into; +use core::fmt; +use core::marker::{Send, Sync}; +use core::option::Option::{self, Some, None}; +use core::result; + use collections::string::String; + +/// A specialized [`Result`](../result/enum.Result.html) type for I/O +/// operations. +/// +/// This type is broadly used across `std::io` for any operation which may +/// produce an error. +/// +/// This typedef is generally used to avoid writing out `io::Error` directly and +/// is otherwise a direct mapping to `Result`. +/// +/// While usual Rust style is to import types directly, aliases of `Result` +/// often are not, to make it easier to distinguish between them. `Result` is +/// generally assumed to be `std::result::Result`, and so users of this alias +/// will generally use `io::Result` instead of shadowing the prelude's import +/// of `std::result::Result`. +/// +/// # Examples +/// +/// A convenience function that bubbles an `io::Result` to its caller: +/// +/// ``` +/// use std::io; +/// +/// fn get_string() -> io::Result { +/// let mut buffer = String::new(); +/// +/// try!(io::stdin().read_line(&mut buffer)); +/// +/// Ok(buffer) +/// } +/// ``` +pub type Result = result::Result; + +/// The error type for I/O operations of the `Read`, `Write`, `Seek`, and +/// associated traits. +/// +/// Errors mostly originate from the underlying OS, but custom instances of +/// `Error` can be created with crafted error messages and a particular value of +/// `ErrorKind`. +#[derive(Debug)] +pub struct Error { + repr: Repr, +} + +enum Repr { + Os(i32), + + Custom(Box), +} + +#[derive(Debug)] +struct Custom { + kind: ErrorKind, + error: String, +} + +/// A list specifying general categories of I/O error. +/// +/// This list is intended to grow over time and it is not recommended to +/// exhaustively match against it. +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[allow(deprecated)] +pub enum ErrorKind { + /// An entity was not found, often a file. + NotFound, + /// The operation lacked the necessary privileges to complete. + PermissionDenied, + /// The connection was refused by the remote server. + ConnectionRefused, + /// The connection was reset by the remote server. + ConnectionReset, + /// The connection was aborted (terminated) by the remote server. + ConnectionAborted, + /// The network operation failed because it was not connected yet. + NotConnected, + /// A socket address could not be bound because the address is already in + /// use elsewhere. + AddrInUse, + /// A nonexistent interface was requested or the requested address was not + /// local. + AddrNotAvailable, + /// The operation failed because a pipe was closed. + BrokenPipe, + /// An entity already exists, often a file. + AlreadyExists, + /// The operation needs to block to complete, but the blocking operation was + /// requested to not occur. + WouldBlock, + /// A parameter was incorrect. + InvalidInput, + /// Data not valid for the operation were encountered. + /// + /// Unlike `InvalidInput`, this typically means that the operation + /// parameters were valid, however the error was caused by malformed + /// input data. + /// + /// For example, a function that reads a file into a string will error with + /// `InvalidData` if the file's contents are not valid UTF-8. + InvalidData, + /// The I/O operation's timeout expired, causing it to be canceled. + TimedOut, + /// An error returned when an operation could not be completed because a + /// call to `write` returned `Ok(0)`. + /// + /// This typically means that an operation could only succeed if it wrote a + /// particular number of bytes but only a smaller number of bytes could be + /// written. + WriteZero, + /// This operation was interrupted. + /// + /// Interrupted operations can typically be retried. + Interrupted, + /// Any I/O error not part of this list. + Other, + + /// An error returned when an operation could not be completed because an + /// "end of file" was reached prematurely. + /// + /// This typically means that an operation could only succeed if it read a + /// particular number of bytes but only a smaller number of bytes could be + /// read. + UnexpectedEof, + + /// Any I/O error not part of this list. + #[doc(hidden)] + __Nonexhaustive, +} + +impl Error { + /// Creates a new I/O error from a known kind of error as well as an + /// arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. The `error` argument is an arbitrary + /// payload which will be contained in this `Error`. + /// + /// # Examples + /// + /// ``` + /// use std::io::{Error, ErrorKind}; + /// + /// // errors can be created from strings + /// let custom_error = Error::new(ErrorKind::Other, "oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); + /// ``` + pub fn new(kind: ErrorKind, error: E) -> Error + where E: Into + { + Self::_new(kind, error.into()) + } + + fn _new(kind: ErrorKind, error: String) -> Error { + Error { + repr: Repr::Custom(Box::new(Custom { + kind: kind, + error: error, + })) + } + } + + /// Creates a new instance of an `Error` from a particular OS error code. + pub fn from_raw_os_error(code: i32) -> Error { + Error { repr: Repr::Os(code) } + } + + /// Returns the OS error that this error represents (if any). + /// + /// If this `Error` was constructed via `last_os_error` or + /// `from_raw_os_error`, then this function will return `Some`, otherwise + /// it will return `None`. + pub fn raw_os_error(&self) -> Option { + match self.repr { + Repr::Os(i) => Some(i), + Repr::Custom(..) => None, + } + } + + /// Returns a reference to the inner error wrapped by this error (if any). + /// + /// If this `Error` was constructed via `new` then this function will + /// return `Some`, otherwise it will return `None`. + pub fn get_ref(&self) -> Option<&String> { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(ref c) => Some(&c.error), + } + } + + /// Returns a mutable reference to the inner error wrapped by this error + /// (if any). + /// + /// If this `Error` was constructed via `new` then this function will + /// return `Some`, otherwise it will return `None`. + pub fn get_mut(&mut self) -> Option<&mut String> { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(ref mut c) => Some(&mut c.error), + } + } + + /// Consumes the `Error`, returning its inner error (if any). + /// + /// If this `Error` was constructed via `new` then this function will + /// return `Some`, otherwise it will return `None`. + pub fn into_inner(self) -> Option { + match self.repr { + Repr::Os(..) => None, + Repr::Custom(c) => Some(c.error) + } + } + + /// Returns the corresponding `ErrorKind` for this error. + pub fn kind(&self) -> ErrorKind { + match self.repr { + Repr::Os(_code) => ErrorKind::Other, + Repr::Custom(ref c) => c.kind, + } + } +} + +impl fmt::Debug for Repr { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + Repr::Os(ref code) => + fmt.debug_struct("Os").field("code", code).finish(), + Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self.repr { + Repr::Os(code) => { + write!(fmt, "os error {}", code) + } + Repr::Custom(ref c) => c.error.fmt(fmt), + } + } +} + +fn _assert_error_is_sync_send() { + fn _is_sync_send() {} + _is_sync_send::(); +} + +#[cfg(test)] +mod test { + use prelude::v1::*; + use super::{Error, ErrorKind}; + use error; + use fmt; + use sys::os::error_string; + + #[test] + fn test_debug_error() { + let code = 6; + let msg = error_string(code); + let err = Error { repr: super::Repr::Os(code) }; + let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg); + assert_eq!(format!("{:?}", err), expected); + } + + #[test] + fn test_downcasting() { + #[derive(Debug)] + struct TestError; + + impl fmt::Display for TestError { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } + } + + impl error::Error for TestError { + fn description(&self) -> &str { + "asdf" + } + } + + // we have to call all of these UFCS style right now since method + // resolution won't implicitly drop the Send+Sync bounds + let mut err = Error::new(ErrorKind::Other, TestError); + assert!(err.get_ref().unwrap().is::()); + assert_eq!("asdf", err.get_ref().unwrap().description()); + assert!(err.get_mut().unwrap().is::()); + let extracted = err.into_inner().unwrap(); + extracted.downcast::().unwrap(); + } +} diff --git a/artiq/runtime.rs/libstd_artiq/io/impls.rs b/artiq/runtime.rs/libstd_artiq/io/impls.rs new file mode 100644 index 000000000..9750cd638 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/impls.rs @@ -0,0 +1,289 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + use alloc::boxed::Box; +use core::cmp; +use io::{self, SeekFrom, Read, Write, Seek, Error, ErrorKind}; + use io::BufRead; +use core::fmt; +use core::mem; + use collections::string::String; + use collections::vec::Vec; + +// ============================================================================= +// Forwarding implementations + +impl<'a, R: Read + ?Sized> Read for &'a mut R { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (**self).read_to_end(buf) + } + + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (**self).read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + (**self).read_exact(buf) + } +} +impl<'a, W: Write + ?Sized> Write for &'a mut W { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } + + #[inline] + fn flush(&mut self) -> io::Result<()> { (**self).flush() } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } +} +impl<'a, S: Seek + ?Sized> Seek for &'a mut S { + #[inline] + fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } +} + +impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B { + #[inline] + fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } + + #[inline] + fn consume(&mut self, amt: usize) { (**self).consume(amt) } + + #[inline] + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result { + (**self).read_until(byte, buf) + } + + #[inline] + fn read_line(&mut self, buf: &mut String) -> io::Result { + (**self).read_line(buf) + } +} + + +impl Read for Box { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (**self).read(buf) + } + + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (**self).read_to_end(buf) + } + + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (**self).read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + (**self).read_exact(buf) + } +} + +impl Write for Box { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { (**self).write(buf) } + + #[inline] + fn flush(&mut self) -> io::Result<()> { (**self).flush() } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (**self).write_all(buf) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { + (**self).write_fmt(fmt) + } +} + +impl Seek for Box { + #[inline] + fn seek(&mut self, pos: SeekFrom) -> io::Result { (**self).seek(pos) } +} + +impl BufRead for Box { + #[inline] + fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() } + + #[inline] + fn consume(&mut self, amt: usize) { (**self).consume(amt) } + + #[inline] + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> io::Result { + (**self).read_until(byte, buf) + } + + #[inline] + fn read_line(&mut self, buf: &mut String) -> io::Result { + (**self).read_line(buf) + } +} + +// ============================================================================= +// In-memory buffer implementations + +impl<'a> Read for &'a [u8] { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let amt = cmp::min(buf.len(), self.len()); + let (a, b) = self.split_at(amt); + buf[..amt].copy_from_slice(a); + *self = b; + Ok(amt) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if buf.len() > self.len() { + return Err(Error::new(ErrorKind::UnexpectedEof, + "failed to fill whole buffer")); + } + let (a, b) = self.split_at(buf.len()); + buf.copy_from_slice(a); + *self = b; + Ok(()) + } +} + + +impl<'a> BufRead for &'a [u8] { + #[inline] + fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) } + + #[inline] + fn consume(&mut self, amt: usize) { *self = &self[amt..]; } +} + +impl<'a> Write for &'a mut [u8] { + #[inline] + fn write(&mut self, data: &[u8]) -> io::Result { + let amt = cmp::min(data.len(), self.len()); + let (a, b) = mem::replace(self, &mut []).split_at_mut(amt); + a.copy_from_slice(&data[..amt]); + *self = b; + Ok(amt) + } + + #[inline] + fn write_all(&mut self, data: &[u8]) -> io::Result<()> { + if self.write(data)? == data.len() { + Ok(()) + } else { + Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) + } + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + + +impl Write for Vec { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.extend_from_slice(buf); + Ok(()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(test)] +mod tests { + use io::prelude::*; + use vec::Vec; + use test; + + #[bench] + fn bench_read_slice(b: &mut test::Bencher) { + let buf = [5; 1024]; + let mut dst = [0; 128]; + + b.iter(|| { + let mut rd = &buf[..]; + for _ in 0..8 { + let _ = rd.read(&mut dst); + test::black_box(&dst); + } + }) + } + + #[bench] + fn bench_write_slice(b: &mut test::Bencher) { + let mut buf = [0; 1024]; + let src = [5; 128]; + + b.iter(|| { + let mut wr = &mut buf[..]; + for _ in 0..8 { + let _ = wr.write_all(&src); + test::black_box(&wr); + } + }) + } + + #[bench] + fn bench_read_vec(b: &mut test::Bencher) { + let buf = vec![5; 1024]; + let mut dst = [0; 128]; + + b.iter(|| { + let mut rd = &buf[..]; + for _ in 0..8 { + let _ = rd.read(&mut dst); + test::black_box(&dst); + } + }) + } + + #[bench] + fn bench_write_vec(b: &mut test::Bencher) { + let mut buf = Vec::with_capacity(1024); + let src = [5; 128]; + + b.iter(|| { + let mut wr = &mut buf[..]; + for _ in 0..8 { + let _ = wr.write_all(&src); + test::black_box(&wr); + } + }) + } +} diff --git a/artiq/runtime.rs/libstd_artiq/io/memchr.rs b/artiq/runtime.rs/libstd_artiq/io/memchr.rs new file mode 100644 index 000000000..110cfac93 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/memchr.rs @@ -0,0 +1,297 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Original implementation taken from rust-memchr +// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch + +pub use self::fallback::{memchr,memrchr}; + +#[allow(dead_code)] +mod fallback { + use core::cmp; + use core::mem; + + const LO_U64: u64 = 0x0101010101010101; + const HI_U64: u64 = 0x8080808080808080; + + // use truncation + const LO_USIZE: usize = LO_U64 as usize; + const HI_USIZE: usize = HI_U64 as usize; + + /// Return `true` if `x` contains any zero byte. + /// + /// From *Matters Computational*, J. Arndt + /// + /// "The idea is to subtract one from each of the bytes and then look for + /// bytes where the borrow propagated all the way to the most significant + /// bit." + #[inline] + fn contains_zero_byte(x: usize) -> bool { + x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 + } + + #[cfg(target_pointer_width = "32")] + #[inline] + fn repeat_byte(b: u8) -> usize { + let mut rep = (b as usize) << 8 | b as usize; + rep = rep << 16 | rep; + rep + } + + #[cfg(target_pointer_width = "64")] + #[inline] + fn repeat_byte(b: u8) -> usize { + let mut rep = (b as usize) << 8 | b as usize; + rep = rep << 16 | rep; + rep = rep << 32 | rep; + rep + } + + /// Return the first index matching the byte `a` in `text`. + pub fn memchr(x: u8, text: &[u8]) -> Option { + // Scan for a single byte value by reading two `usize` words at a time. + // + // Split `text` in three parts + // - unaligned initial part, before the first word aligned address in text + // - body, scan by 2 words at a time + // - the last remaining part, < 2 word size + let len = text.len(); + let ptr = text.as_ptr(); + let usize_bytes = mem::size_of::(); + + // search up to an aligned boundary + let align = (ptr as usize) & (usize_bytes- 1); + let mut offset; + if align > 0 { + offset = cmp::min(usize_bytes - align, len); + if let Some(index) = text[..offset].iter().position(|elt| *elt == x) { + return Some(index); + } + } else { + offset = 0; + } + + // search the body of the text + let repeated_x = repeat_byte(x); + + if len >= 2 * usize_bytes { + while offset <= len - 2 * usize_bytes { + unsafe { + let u = *(ptr.offset(offset as isize) as *const usize); + let v = *(ptr.offset((offset + usize_bytes) as isize) as *const usize); + + // break if there is a matching byte + let zu = contains_zero_byte(u ^ repeated_x); + let zv = contains_zero_byte(v ^ repeated_x); + if zu || zv { + break; + } + } + offset += usize_bytes * 2; + } + } + + // find the byte after the point the body loop stopped + text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i) + } + + /// Return the last index matching the byte `a` in `text`. + pub fn memrchr(x: u8, text: &[u8]) -> Option { + // Scan for a single byte value by reading two `usize` words at a time. + // + // Split `text` in three parts + // - unaligned tail, after the last word aligned address in text + // - body, scan by 2 words at a time + // - the first remaining bytes, < 2 word size + let len = text.len(); + let ptr = text.as_ptr(); + let usize_bytes = mem::size_of::(); + + // search to an aligned boundary + let end_align = (ptr as usize + len) & (usize_bytes - 1); + let mut offset; + if end_align > 0 { + offset = len - cmp::min(usize_bytes - end_align, len); + if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) { + return Some(offset + index); + } + } else { + offset = len; + } + + // search the body of the text + let repeated_x = repeat_byte(x); + + while offset >= 2 * usize_bytes { + unsafe { + let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize); + let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize); + + // break if there is a matching byte + let zu = contains_zero_byte(u ^ repeated_x); + let zv = contains_zero_byte(v ^ repeated_x); + if zu || zv { + break; + } + } + offset -= 2 * usize_bytes; + } + + // find the byte before the point the body loop stopped + text[..offset].iter().rposition(|elt| *elt == x) + } + + // test fallback implementations on all plattforms + #[test] + fn matches_one() { + assert_eq!(Some(0), memchr(b'a', b"a")); + } + + #[test] + fn matches_begin() { + assert_eq!(Some(0), memchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end() { + assert_eq!(Some(4), memchr(b'z', b"aaaaz")); + } + + #[test] + fn matches_nul() { + assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul() { + assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); + } + + #[test] + fn no_match_empty() { + assert_eq!(None, memchr(b'a', b"")); + } + + #[test] + fn no_match() { + assert_eq!(None, memchr(b'a', b"xyz")); + } + + #[test] + fn matches_one_reversed() { + assert_eq!(Some(0), memrchr(b'a', b"a")); + } + + #[test] + fn matches_begin_reversed() { + assert_eq!(Some(3), memrchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); + } + + #[test] + fn matches_nul_reversed() { + assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); + } + + #[test] + fn no_match_empty_reversed() { + assert_eq!(None, memrchr(b'a', b"")); + } + + #[test] + fn no_match_reversed() { + assert_eq!(None, memrchr(b'a', b"xyz")); + } +} + +#[cfg(test)] +mod tests { + // test the implementations for the current plattform + use super::{memchr, memrchr}; + + #[test] + fn matches_one() { + assert_eq!(Some(0), memchr(b'a', b"a")); + } + + #[test] + fn matches_begin() { + assert_eq!(Some(0), memchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end() { + assert_eq!(Some(4), memchr(b'z', b"aaaaz")); + } + + #[test] + fn matches_nul() { + assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul() { + assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); + } + + #[test] + fn no_match_empty() { + assert_eq!(None, memchr(b'a', b"")); + } + + #[test] + fn no_match() { + assert_eq!(None, memchr(b'a', b"xyz")); + } + + #[test] + fn matches_one_reversed() { + assert_eq!(Some(0), memrchr(b'a', b"a")); + } + + #[test] + fn matches_begin_reversed() { + assert_eq!(Some(3), memrchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); + } + + #[test] + fn matches_nul_reversed() { + assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); + } + + #[test] + fn no_match_empty_reversed() { + assert_eq!(None, memrchr(b'a', b"")); + } + + #[test] + fn no_match_reversed() { + assert_eq!(None, memrchr(b'a', b"xyz")); + } +} diff --git a/artiq/runtime.rs/libstd_artiq/io/mod.rs b/artiq/runtime.rs/libstd_artiq/io/mod.rs new file mode 100644 index 000000000..e1ea29969 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/mod.rs @@ -0,0 +1,1845 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Traits, helpers, and type definitions for core I/O functionality. +//! +//! The `std::io` module contains a number of common things you'll need +//! when doing input and output. The most core part of this module is +//! the [`Read`][read] and [`Write`][write] traits, which provide the +//! most general interface for reading and writing input and output. +//! +//! [read]: trait.Read.html +//! [write]: trait.Write.html +//! +//! # Read and Write +//! +//! Because they are traits, `Read` and `Write` are implemented by a number +//! of other types, and you can implement them for your types too. As such, +//! you'll see a few different types of I/O throughout the documentation in +//! this module: `File`s, `TcpStream`s, and sometimes even `Vec`s. For +//! example, `Read` adds a `read()` method, which we can use on `File`s: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! use std::fs::File; +//! +//! # fn foo() -> io::Result<()> { +//! let mut f = try!(File::open("foo.txt")); +//! let mut buffer = [0; 10]; +//! +//! // read up to 10 bytes +//! try!(f.read(&mut buffer)); +//! +//! println!("The bytes: {:?}", buffer); +//! # Ok(()) +//! # } +//! ``` +//! +//! `Read` and `Write` are so important, implementors of the two traits have a +//! nickname: readers and writers. So you'll sometimes see 'a reader' instead +//! of 'a type that implements the `Read` trait'. Much easier! +//! +//! ## Seek and BufRead +//! +//! Beyond that, there are two important traits that are provided: [`Seek`][seek] +//! and [`BufRead`][bufread]. Both of these build on top of a reader to control +//! how the reading happens. `Seek` lets you control where the next byte is +//! coming from: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::SeekFrom; +//! use std::fs::File; +//! +//! # fn foo() -> io::Result<()> { +//! let mut f = try!(File::open("foo.txt")); +//! let mut buffer = [0; 10]; +//! +//! // skip to the last 10 bytes of the file +//! try!(f.seek(SeekFrom::End(-10))); +//! +//! // read up to 10 bytes +//! try!(f.read(&mut buffer)); +//! +//! println!("The bytes: {:?}", buffer); +//! # Ok(()) +//! # } +//! ``` +//! +//! [seek]: trait.Seek.html +//! [bufread]: trait.BufRead.html +//! +//! `BufRead` uses an internal buffer to provide a number of other ways to read, but +//! to show it off, we'll need to talk about buffers in general. Keep reading! +//! +//! ## BufReader and BufWriter +//! +//! Byte-based interfaces are unwieldy and can be inefficient, as we'd need to be +//! making near-constant calls to the operating system. To help with this, +//! `std::io` comes with two structs, `BufReader` and `BufWriter`, which wrap +//! readers and writers. The wrapper uses a buffer, reducing the number of +//! calls and providing nicer methods for accessing exactly what you want. +//! +//! For example, `BufReader` works with the `BufRead` trait to add extra +//! methods to any reader: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufReader; +//! use std::fs::File; +//! +//! # fn foo() -> io::Result<()> { +//! let f = try!(File::open("foo.txt")); +//! let mut reader = BufReader::new(f); +//! let mut buffer = String::new(); +//! +//! // read a line into buffer +//! try!(reader.read_line(&mut buffer)); +//! +//! println!("{}", buffer); +//! # Ok(()) +//! # } +//! ``` +//! +//! `BufWriter` doesn't add any new ways of writing; it just buffers every call +//! to [`write()`][write()]: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufWriter; +//! use std::fs::File; +//! +//! # fn foo() -> io::Result<()> { +//! let f = try!(File::create("foo.txt")); +//! { +//! let mut writer = BufWriter::new(f); +//! +//! // write a byte to the buffer +//! try!(writer.write(&[42])); +//! +//! } // the buffer is flushed once writer goes out of scope +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! [write()]: trait.Write.html#tymethod.write +//! +//! ## Standard input and output +//! +//! A very common source of input is standard input: +//! +//! ``` +//! use std::io; +//! +//! # fn foo() -> io::Result<()> { +//! let mut input = String::new(); +//! +//! try!(io::stdin().read_line(&mut input)); +//! +//! println!("You typed: {}", input.trim()); +//! # Ok(()) +//! # } +//! ``` +//! +//! And a very common source of output is standard output: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! +//! # fn foo() -> io::Result<()> { +//! try!(io::stdout().write(&[42])); +//! # Ok(()) +//! # } +//! ``` +//! +//! Of course, using `io::stdout()` directly is less common than something like +//! `println!`. +//! +//! ## Iterator types +//! +//! A large number of the structures provided by `std::io` are for various +//! ways of iterating over I/O. For example, `Lines` is used to split over +//! lines: +//! +//! ``` +//! use std::io; +//! use std::io::prelude::*; +//! use std::io::BufReader; +//! use std::fs::File; +//! +//! # fn foo() -> io::Result<()> { +//! let f = try!(File::open("foo.txt")); +//! let reader = BufReader::new(f); +//! +//! for line in reader.lines() { +//! println!("{}", try!(line)); +//! } +//! +//! # Ok(()) +//! # } +//! ``` +//! +//! ## Functions +//! +//! There are a number of [functions][functions-list] that offer access to various +//! features. For example, we can use three of these functions to copy everything +//! from standard input to standard output: +//! +//! ``` +//! use std::io; +//! +//! # fn foo() -> io::Result<()> { +//! try!(io::copy(&mut io::stdin(), &mut io::stdout())); +//! # Ok(()) +//! # } +//! ``` +//! +//! [functions-list]: #functions-1 +//! +//! ## io::Result +//! +//! Last, but certainly not least, is [`io::Result`][result]. This type is used +//! as the return type of many `std::io` functions that can cause an error, and +//! can be returned from your own functions as well. Many of the examples in this +//! module use the [`try!`][try] macro: +//! +//! ``` +//! use std::io; +//! +//! fn read_input() -> io::Result<()> { +//! let mut input = String::new(); +//! +//! try!(io::stdin().read_line(&mut input)); +//! +//! println!("You typed: {}", input.trim()); +//! +//! Ok(()) +//! } +//! ``` +//! +//! The return type of `read_input()`, `io::Result<()>`, is a very common type +//! for functions which don't have a 'real' return value, but do want to return +//! errors if they happen. In this case, the only purpose of this function is +//! to read the line and print it, so we use `()`. +//! +//! [result]: type.Result.html +//! [try]: ../macro.try!.html +//! +//! ## Platform-specific behavior +//! +//! Many I/O functions throughout the standard library are documented to indicate +//! what various library or syscalls they are delegated to. This is done to help +//! applications both understand what's happening under the hood as well as investigate +//! any possibly unclear semantics. Note, however, that this is informative, not a binding +//! contract. The implementation of many of these functions are subject to change over +//! time and may call fewer or more syscalls/library functions. + +use core::cmp; +use rustc_unicode::str as core_str; +use core::fmt; +use core::iter::{Iterator}; +use core::marker::Sized; + use core::ops::{Drop, FnOnce}; +use core::option::Option::{self, Some, None}; +use core::result::Result::{Ok, Err}; +use core::result; + use collections::string::String; + use collections::vec::Vec; + use collections::str; +mod memchr; + + pub use self::buffered::{BufReader, BufWriter, LineWriter}; + pub use self::buffered::IntoInnerError; + pub use self::cursor::Cursor; +pub use self::error::{Result, Error, ErrorKind}; +pub use self::util::{copy, sink, Sink, empty, Empty, repeat, Repeat}; + +pub mod prelude; + mod buffered; + mod cursor; +mod error; +mod impls; +mod util; + +const DEFAULT_BUF_SIZE: usize = 8 * 1024; + +// A few methods below (read_to_string, read_line) will append data into a +// `String` buffer, but we need to be pretty careful when doing this. The +// implementation will just call `.as_mut_vec()` and then delegate to a +// byte-oriented reading method, but we must ensure that when returning we never +// leave `buf` in a state such that it contains invalid UTF-8 in its bounds. +// +// To this end, we use an RAII guard (to protect against panics) which updates +// the length of the string when it is dropped. This guard initially truncates +// the string to the prior length and only after we've validated that the +// new contents are valid UTF-8 do we allow it to set a longer length. +// +// The unsafety in this function is twofold: +// +// 1. We're looking at the raw bytes of `buf`, so we take on the burden of UTF-8 +// checks. +// 2. We're passing a raw buffer to the function `f`, and it is expected that +// the function only *appends* bytes to the buffer. We'll get undefined +// behavior if existing bytes are overwritten to have non-UTF-8 data. + +fn append_to_string(buf: &mut String, f: F) -> Result + where F: FnOnce(&mut Vec) -> Result +{ + struct Guard<'a> { s: &'a mut Vec, len: usize } + impl<'a> Drop for Guard<'a> { + fn drop(&mut self) { + unsafe { self.s.set_len(self.len); } + } + } + + unsafe { + let mut g = Guard { len: buf.len(), s: buf.as_mut_vec() }; + let ret = f(g.s); + if str::from_utf8(&g.s[g.len..]).is_err() { + ret.and_then(|_| { + Err(Error::new(ErrorKind::InvalidData, + "stream did not contain valid UTF-8")) + }) + } else { + g.len = g.s.len(); + ret + } + } +} + +// This uses an adaptive system to extend the vector when it fills. We want to +// avoid paying to allocate and zero a huge chunk of memory if the reader only +// has 4 bytes while still making large reads if the reader does have a ton +// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every +// time is 4,500 times (!) slower than this if the reader has a very small +// amount of data to return. + +fn read_to_end(r: &mut R, buf: &mut Vec) -> Result { + let start_len = buf.len(); + let mut len = start_len; + let mut new_write_size = 16; + let ret; + loop { + if len == buf.len() { + if new_write_size < DEFAULT_BUF_SIZE { + new_write_size *= 2; + } + buf.resize(len + new_write_size, 0); + } + + match r.read(&mut buf[len..]) { + Ok(0) => { + ret = Ok(len - start_len); + break; + } + Ok(n) => len += n, + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => { + ret = Err(e); + break; + } + } + } + + buf.truncate(len); + ret +} + +/// The `Read` trait allows for reading bytes from a source. +/// +/// Implementors of the `Read` trait are sometimes called 'readers'. +/// +/// Readers are defined by one required method, `read()`. Each call to `read` +/// will attempt to pull bytes from this source into a provided buffer. A +/// number of other methods are implemented in terms of `read()`, giving +/// implementors a number of ways to read bytes while only needing to implement +/// a single method. +/// +/// Readers are intended to be composable with one another. Many implementors +/// throughout `std::io` take and provide types which implement the `Read` +/// trait. +/// +/// Please note that each call to `read` may involve a system call, and +/// therefore, using something that implements [`BufRead`][bufread], such as +/// [`BufReader`][bufreader], will be more efficient. +/// +/// [bufread]: trait.BufRead.html +/// [bufreader]: struct.BufReader.html +/// +/// # Examples +/// +/// [`File`][file]s implement `Read`: +/// +/// [file]: ../fs/struct.File.html +/// +/// ``` +/// use std::io; +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// # fn foo() -> io::Result<()> { +/// let mut f = try!(File::open("foo.txt")); +/// let mut buffer = [0; 10]; +/// +/// // read up to 10 bytes +/// try!(f.read(&mut buffer)); +/// +/// let mut buffer = vec![0; 10]; +/// // read the whole file +/// try!(f.read_to_end(&mut buffer)); +/// +/// // read into a String, so that you don't need to do the conversion. +/// let mut buffer = String::new(); +/// try!(f.read_to_string(&mut buffer)); +/// +/// // and more! See the other methods for more details. +/// # Ok(()) +/// # } +/// ``` +pub trait Read { + /// Pull some bytes from this source into the specified buffer, returning + /// how many bytes were read. + /// + /// This function does not provide any guarantees about whether it blocks + /// waiting for data, but if an object needs to block for a read but cannot + /// it will typically signal this via an `Err` return value. + /// + /// If the return value of this method is `Ok(n)`, then it must be + /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates + /// that the buffer `buf` has been filled in with `n` bytes of data from this + /// source. If `n` is `0`, then it can indicate one of two scenarios: + /// + /// 1. This reader has reached its "end of file" and will likely no longer + /// be able to produce bytes. Note that this does not mean that the + /// reader will *always* no longer be able to produce bytes. + /// 2. The buffer specified was 0 bytes in length. + /// + /// No guarantees are provided about the contents of `buf` when this + /// function is called, implementations cannot rely on any property of the + /// contents of `buf` being true. It is recommended that implementations + /// only write data to `buf` instead of reading its contents. + /// + /// # Errors + /// + /// If this function encounters any form of I/O or other error, an error + /// variant will be returned. If an error is returned then it must be + /// guaranteed that no bytes were read. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let mut buffer = [0; 10]; + /// + /// // read 10 bytes + /// try!(f.read(&mut buffer[..])); + /// # Ok(()) + /// # } + /// ``` + fn read(&mut self, buf: &mut [u8]) -> Result; + + /// Read all bytes until EOF in this source, placing them into `buf`. + /// + /// All bytes read from this source will be appended to the specified buffer + /// `buf`. This function will continuously call `read` to append more data to + /// `buf` until `read` returns either `Ok(0)` or an error of + /// non-`ErrorKind::Interrupted` kind. + /// + /// If successful, this function will return the total number of bytes read. + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// `ErrorKind::Interrupted` then the error is ignored and the operation + /// will continue. + /// + /// If any other read error is encountered then this function immediately + /// returns. Any bytes which have already been read will be appended to + /// `buf`. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let mut buffer = Vec::new(); + /// + /// // read the whole file + /// try!(f.read_to_end(&mut buffer)); + /// # Ok(()) + /// # } + /// ``` + + fn read_to_end(&mut self, buf: &mut Vec) -> Result { + read_to_end(self, buf) + } + + /// Read all bytes until EOF in this source, placing them into `buf`. + /// + /// If successful, this function returns the number of bytes which were read + /// and appended to `buf`. + /// + /// # Errors + /// + /// If the data in this stream is *not* valid UTF-8 then an error is + /// returned and `buf` is unchanged. + /// + /// See [`read_to_end()`][readtoend] for other error semantics. + /// + /// [readtoend]: #method.read_to_end + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let mut buffer = String::new(); + /// + /// try!(f.read_to_string(&mut buffer)); + /// # Ok(()) + /// # } + /// ``` + + fn read_to_string(&mut self, buf: &mut String) -> Result { + // Note that we do *not* call `.read_to_end()` here. We are passing + // `&mut Vec` (the raw contents of `buf`) into the `read_to_end` + // method to fill it up. An arbitrary implementation could overwrite the + // entire contents of the vector, not just append to it (which is what + // we are expecting). + // + // To prevent extraneously checking the UTF-8-ness of the entire buffer + // we pass it to our hardcoded `read_to_end` implementation which we + // know is guaranteed to only read data into the end of the buffer. + append_to_string(buf, |b| read_to_end(self, b)) + } + + /// Read the exact number of bytes required to fill `buf`. + /// + /// This function reads as many bytes as necessary to completely fill the + /// specified buffer `buf`. + /// + /// No guarantees are provided about the contents of `buf` when this + /// function is called, implementations cannot rely on any property of the + /// contents of `buf` being true. It is recommended that implementations + /// only write data to `buf` instead of reading its contents. + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// `ErrorKind::Interrupted` then the error is ignored and the operation + /// will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind `ErrorKind::UnexpectedEof`. + /// The contents of `buf` are unspecified in this case. + /// + /// If any other read error is encountered then this function immediately + /// returns. The contents of `buf` are unspecified in this case. + /// + /// If this function returns an error, it is unspecified how many bytes it + /// has read, but it will never read more than would be necessary to + /// completely fill the buffer. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let mut buffer = [0; 10]; + /// + /// // read exactly 10 bytes + /// try!(f.read_exact(&mut buffer)); + /// # Ok(()) + /// # } + /// ``` + fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<()> { + while !buf.is_empty() { + match self.read(buf) { + Ok(0) => break, + Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; } + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + if !buf.is_empty() { + Err(Error::new(ErrorKind::UnexpectedEof, + "failed to fill whole buffer")) + } else { + Ok(()) + } + } + + /// Creates a "by reference" adaptor for this instance of `Read`. + /// + /// The returned adaptor also implements `Read` and will simply borrow this + /// current reader. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::Read; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let mut buffer = Vec::new(); + /// let mut other_buffer = Vec::new(); + /// + /// { + /// let reference = f.by_ref(); + /// + /// // read at most 5 bytes + /// try!(reference.take(5).read_to_end(&mut buffer)); + /// + /// } // drop our &mut reference so we can use f again + /// + /// // original file still usable, read the rest + /// try!(f.read_to_end(&mut other_buffer)); + /// # Ok(()) + /// # } + /// ``` + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } + + /// Transforms this `Read` instance to an `Iterator` over its bytes. + /// + /// The returned type implements `Iterator` where the `Item` is `Result`. The yielded item is `Ok` if a byte was successfully read and + /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from + /// this iterator. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// + /// for byte in f.bytes() { + /// println!("{}", byte.unwrap()); + /// } + /// # Ok(()) + /// # } + /// ``` + fn bytes(self) -> Bytes where Self: Sized { + Bytes { inner: self } + } + + /// Transforms this `Read` instance to an `Iterator` over `char`s. + /// + /// This adaptor will attempt to interpret this reader as a UTF-8 encoded + /// sequence of characters. The returned iterator will return `None` once + /// EOF is reached for this reader. Otherwise each element yielded will be a + /// `Result` where `E` may contain information about what I/O error + /// occurred or where decoding failed. + /// + /// Currently this adaptor will discard intermediate data read, and should + /// be avoided if this is not desired. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// #![feature(io)] + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// + /// for c in f.chars() { + /// println!("{}", c.unwrap()); + /// } + /// # Ok(()) + /// # } + /// ``` + fn chars(self) -> Chars where Self: Sized { + Chars { inner: self } + } + + /// Creates an adaptor which will chain this stream with another. + /// + /// The returned `Read` instance will first read all bytes from this object + /// until EOF is encountered. Afterwards the output is equivalent to the + /// output of `next`. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f1 = try!(File::open("foo.txt")); + /// let mut f2 = try!(File::open("bar.txt")); + /// + /// let mut handle = f1.chain(f2); + /// let mut buffer = String::new(); + /// + /// // read the value into a String. We could use any Read method here, + /// // this is just one example. + /// try!(handle.read_to_string(&mut buffer)); + /// # Ok(()) + /// # } + /// ``` + fn chain(self, next: R) -> Chain where Self: Sized { + Chain { first: self, second: next, done_first: false } + } + + /// Creates an adaptor which will read at most `limit` bytes from it. + /// + /// This function returns a new instance of `Read` which will read at most + /// `limit` bytes, after which it will always return EOF (`Ok(0)`). Any + /// read errors will not count towards the number of bytes read and future + /// calls to `read` may succeed. + /// + /// # Examples + /// + /// [`File`][file]s implement `Read`: + /// + /// [file]: ../fs/struct.File.html + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> io::Result<()> { + /// let mut f = try!(File::open("foo.txt")); + /// let mut buffer = [0; 5]; + /// + /// // read at most five bytes + /// let mut handle = f.take(5); + /// + /// try!(handle.read(&mut buffer)); + /// # Ok(()) + /// # } + /// ``` + fn take(self, limit: u64) -> Take where Self: Sized { + Take { inner: self, limit: limit } + } +} + +/// A trait for objects which are byte-oriented sinks. +/// +/// Implementors of the `Write` trait are sometimes called 'writers'. +/// +/// Writers are defined by two required methods, `write()` and `flush()`: +/// +/// * The `write()` method will attempt to write some data into the object, +/// returning how many bytes were successfully written. +/// +/// * The `flush()` method is useful for adaptors and explicit buffers +/// themselves for ensuring that all buffered data has been pushed out to the +/// 'true sink'. +/// +/// Writers are intended to be composable with one another. Many implementors +/// throughout `std::io` take and provide types which implement the `Write` +/// trait. +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// # fn foo() -> std::io::Result<()> { +/// let mut buffer = try!(File::create("foo.txt")); +/// +/// try!(buffer.write(b"some bytes")); +/// # Ok(()) +/// # } +/// ``` +pub trait Write { + /// Write a buffer into this object, returning how many bytes were written. + /// + /// This function will attempt to write the entire contents of `buf`, but + /// the entire write may not succeed, or the write may also generate an + /// error. A call to `write` represents *at most one* attempt to write to + /// any wrapped object. + /// + /// Calls to `write` are not guaranteed to block waiting for data to be + /// written, and a write which would otherwise block can be indicated through + /// an `Err` variant. + /// + /// If the return value is `Ok(n)` then it must be guaranteed that + /// `0 <= n <= buf.len()`. A return value of `0` typically means that the + /// underlying object is no longer able to accept bytes and will likely not + /// be able to in the future as well, or that the buffer provided is empty. + /// + /// # Errors + /// + /// Each call to `write` may generate an I/O error indicating that the + /// operation could not be completed. If an error is returned then no bytes + /// in the buffer were written to this writer. + /// + /// It is **not** considered an error if the entire buffer could not be + /// written to this writer. + /// + /// # Examples + /// + /// ``` + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut buffer = try!(File::create("foo.txt")); + /// + /// try!(buffer.write(b"some bytes")); + /// # Ok(()) + /// # } + /// ``` + fn write(&mut self, buf: &[u8]) -> Result; + + /// Flush this output stream, ensuring that all intermediately buffered + /// contents reach their destination. + /// + /// # Errors + /// + /// It is considered an error if not all bytes could be written due to + /// I/O errors or EOF being reached. + /// + /// # Examples + /// + /// ``` + /// use std::io::prelude::*; + /// use std::io::BufWriter; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut buffer = BufWriter::new(try!(File::create("foo.txt"))); + /// + /// try!(buffer.write(b"some bytes")); + /// try!(buffer.flush()); + /// # Ok(()) + /// # } + /// ``` + fn flush(&mut self) -> Result<()>; + + /// Attempts to write an entire buffer into this write. + /// + /// This method will continuously call `write` while there is more data to + /// write. This method will not return until the entire buffer has been + /// successfully written or an error occurs. The first error generated from + /// this method will be returned. + /// + /// # Errors + /// + /// This function will return the first error that `write` returns. + /// + /// # Examples + /// + /// ``` + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut buffer = try!(File::create("foo.txt")); + /// + /// try!(buffer.write_all(b"some bytes")); + /// # Ok(()) + /// # } + /// ``` + fn write_all(&mut self, mut buf: &[u8]) -> Result<()> { + while !buf.is_empty() { + match self.write(buf) { + Ok(0) => return Err(Error::new(ErrorKind::WriteZero, + "failed to write whole buffer")), + Ok(n) => buf = &buf[n..], + Err(ref e) if e.kind() == ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } + + /// Writes a formatted string into this writer, returning any error + /// encountered. + /// + /// This method is primarily used to interface with the + /// [`format_args!`][formatargs] macro, but it is rare that this should + /// explicitly be called. The [`write!`][write] macro should be favored to + /// invoke this method instead. + /// + /// [formatargs]: ../macro.format_args!.html + /// [write]: ../macro.write!.html + /// + /// This function internally uses the [`write_all`][writeall] method on + /// this trait and hence will continuously write data so long as no errors + /// are received. This also means that partial writes are not indicated in + /// this signature. + /// + /// [writeall]: #method.write_all + /// + /// # Errors + /// + /// This function will return any I/O error reported while formatting. + /// + /// # Examples + /// + /// ``` + /// use std::io::prelude::*; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut buffer = try!(File::create("foo.txt")); + /// + /// // this call + /// try!(write!(buffer, "{:.*}", 2, 1.234567)); + /// // turns into this: + /// try!(buffer.write_fmt(format_args!("{:.*}", 2, 1.234567))); + /// # Ok(()) + /// # } + /// ``` + fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()> { + // Create a shim which translates a Write to a fmt::Write and saves + // off I/O errors. instead of discarding them + struct Adaptor<'a, T: ?Sized + 'a> { + inner: &'a mut T, + error: Result<()>, + } + + impl<'a, T: Write + ?Sized> fmt::Write for Adaptor<'a, T> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.inner.write_all(s.as_bytes()) { + Ok(()) => Ok(()), + Err(e) => { + self.error = Err(e); + Err(fmt::Error) + } + } + } + } + + let mut output = Adaptor { inner: self, error: Ok(()) }; + match fmt::write(&mut output, fmt) { + Ok(()) => Ok(()), + Err(..) => { + // check if the error came from the underlying `Write` or not + if output.error.is_err() { + output.error + } else { + Err(Error::new(ErrorKind::Other, "formatter error")) + } + } + } + } + + /// Creates a "by reference" adaptor for this instance of `Write`. + /// + /// The returned adaptor also implements `Write` and will simply borrow this + /// current writer. + /// + /// # Examples + /// + /// ``` + /// use std::io::Write; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let mut buffer = try!(File::create("foo.txt")); + /// + /// let reference = buffer.by_ref(); + /// + /// // we can use reference just like our original buffer + /// try!(reference.write_all(b"some bytes")); + /// # Ok(()) + /// # } + /// ``` + fn by_ref(&mut self) -> &mut Self where Self: Sized { self } +} + +/// The `Seek` trait provides a cursor which can be moved within a stream of +/// bytes. +/// +/// The stream typically has a fixed size, allowing seeking relative to either +/// end or the current offset. +/// +/// # Examples +/// +/// [`File`][file]s implement `Seek`: +/// +/// [file]: ../fs/struct.File.html +/// +/// ``` +/// use std::io; +/// use std::io::prelude::*; +/// use std::fs::File; +/// use std::io::SeekFrom; +/// +/// # fn foo() -> io::Result<()> { +/// let mut f = try!(File::open("foo.txt")); +/// +/// // move the cursor 42 bytes from the start of the file +/// try!(f.seek(SeekFrom::Start(42))); +/// # Ok(()) +/// # } +/// ``` +pub trait Seek { + /// Seek to an offset, in bytes, in a stream. + /// + /// A seek beyond the end of a stream is allowed, but implementation + /// defined. + /// + /// If the seek operation completed successfully, + /// this method returns the new position from the start of the stream. + /// That position can be used later with `SeekFrom::Start`. + /// + /// # Errors + /// + /// Seeking to a negative offset is considered an error. + fn seek(&mut self, pos: SeekFrom) -> Result; +} + +/// Enumeration of possible methods to seek within an I/O object. +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +pub enum SeekFrom { + /// Set the offset to the provided number of bytes. + Start(u64), + + /// Set the offset to the size of this object plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + End(i64), + + /// Set the offset to the current position plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error to + /// seek before byte 0. + Current(i64), +} + + +fn read_until(r: &mut R, delim: u8, buf: &mut Vec) + -> Result { + let mut read = 0; + loop { + let (done, used) = { + let available = match r.fill_buf() { + Ok(n) => n, + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e) + }; + match memchr::memchr(delim, available) { + Some(i) => { + buf.extend_from_slice(&available[..i + 1]); + (true, i + 1) + } + None => { + buf.extend_from_slice(available); + (false, available.len()) + } + } + }; + r.consume(used); + read += used; + if done || used == 0 { + return Ok(read); + } + } +} + +/// A `BufRead` is a type of `Read`er which has an internal buffer, allowing it +/// to perform extra ways of reading. +/// +/// For example, reading line-by-line is inefficient without using a buffer, so +/// if you want to read by line, you'll need `BufRead`, which includes a +/// [`read_line()`][readline] method as well as a [`lines()`][lines] iterator. +/// +/// [readline]: #method.read_line +/// [lines]: #method.lines +/// +/// # Examples +/// +/// A locked standard input implements `BufRead`: +/// +/// ``` +/// use std::io; +/// use std::io::prelude::*; +/// +/// let stdin = io::stdin(); +/// for line in stdin.lock().lines() { +/// println!("{}", line.unwrap()); +/// } +/// ``` +/// +/// If you have something that implements `Read`, you can use the [`BufReader` +/// type][bufreader] to turn it into a `BufRead`. +/// +/// For example, [`File`][file] implements `Read`, but not `BufRead`. +/// `BufReader` to the rescue! +/// +/// [bufreader]: struct.BufReader.html +/// [file]: ../fs/struct.File.html +/// +/// ``` +/// use std::io::{self, BufReader}; +/// use std::io::prelude::*; +/// use std::fs::File; +/// +/// # fn foo() -> io::Result<()> { +/// let f = try!(File::open("foo.txt")); +/// let f = BufReader::new(f); +/// +/// for line in f.lines() { +/// println!("{}", line.unwrap()); +/// } +/// +/// # Ok(()) +/// # } +/// ``` +/// + +pub trait BufRead: Read { + /// Fills the internal buffer of this object, returning the buffer contents. + /// + /// This function is a lower-level call. It needs to be paired with the + /// [`consume`][consume] method to function properly. When calling this + /// method, none of the contents will be "read" in the sense that later + /// calling `read` may return the same contents. As such, `consume` must be + /// called with the number of bytes that are consumed from this buffer to + /// ensure that the bytes are never returned twice. + /// + /// [consume]: #tymethod.consume + /// + /// An empty buffer returned indicates that the stream has reached EOF. + /// + /// # Errors + /// + /// This function will return an I/O error if the underlying reader was + /// read, but returned an error. + /// + /// # Examples + /// + /// A locked standard input implements `BufRead`: + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// let mut stdin = stdin.lock(); + /// + /// // we can't have two `&mut` references to `stdin`, so use a block + /// // to end the borrow early. + /// let length = { + /// let buffer = stdin.fill_buf().unwrap(); + /// + /// // work with buffer + /// println!("{:?}", buffer); + /// + /// buffer.len() + /// }; + /// + /// // ensure the bytes we worked with aren't returned again later + /// stdin.consume(length); + /// ``` + fn fill_buf(&mut self) -> Result<&[u8]>; + + /// Tells this buffer that `amt` bytes have been consumed from the buffer, + /// so they should no longer be returned in calls to `read`. + /// + /// This function is a lower-level call. It needs to be paired with the + /// [`fill_buf`][fillbuf] method to function properly. This function does + /// not perform any I/O, it simply informs this object that some amount of + /// its buffer, returned from `fill_buf`, has been consumed and should no + /// longer be returned. As such, this function may do odd things if + /// `fill_buf` isn't called before calling it. + /// + /// [fillbuf]: #tymethod.fill_buf + /// + /// The `amt` must be `<=` the number of bytes in the buffer returned by + /// `fill_buf`. + /// + /// # Examples + /// + /// Since `consume()` is meant to be used with [`fill_buf()`][fillbuf], + /// that method's example includes an example of `consume()`. + fn consume(&mut self, amt: usize); + + /// Read all bytes into `buf` until the delimiter `byte` is reached. + /// + /// This function will read bytes from the underlying stream until the + /// delimiter or EOF is found. Once found, all bytes up to, and including, + /// the delimiter (if found) will be appended to `buf`. + /// + /// If this reader is currently at EOF then this function will not modify + /// `buf` and will return `Ok(n)` where `n` is the number of bytes which + /// were read. + /// + /// # Errors + /// + /// This function will ignore all instances of `ErrorKind::Interrupted` and + /// will otherwise return any errors returned by `fill_buf`. + /// + /// If an I/O error is encountered then all bytes read so far will be + /// present in `buf` and its length will have been adjusted appropriately. + /// + /// # Examples + /// + /// A locked standard input implements `BufRead`. In this example, we'll + /// read from standard input until we see an `a` byte. + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// + /// fn foo() -> io::Result<()> { + /// let stdin = io::stdin(); + /// let mut stdin = stdin.lock(); + /// let mut buffer = Vec::new(); + /// + /// try!(stdin.read_until(b'a', &mut buffer)); + /// + /// println!("{:?}", buffer); + /// # Ok(()) + /// # } + /// ``` + fn read_until(&mut self, byte: u8, buf: &mut Vec) -> Result { + read_until(self, byte, buf) + } + + /// Read all bytes until a newline (the 0xA byte) is reached, and append + /// them to the provided buffer. + /// + /// This function will read bytes from the underlying stream until the + /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes + /// up to, and including, the delimiter (if found) will be appended to + /// `buf`. + /// + /// If this reader is currently at EOF then this function will not modify + /// `buf` and will return `Ok(n)` where `n` is the number of bytes which + /// were read. + /// + /// # Errors + /// + /// This function has the same error semantics as `read_until` and will also + /// return an error if the read bytes are not valid UTF-8. If an I/O error + /// is encountered then `buf` may contain some bytes already read in the + /// event that all data read so far was valid UTF-8. + /// + /// # Examples + /// + /// A locked standard input implements `BufRead`. In this example, we'll + /// read all of the lines from standard input. If we were to do this in + /// an actual project, the [`lines()`][lines] method would be easier, of + /// course. + /// + /// [lines]: #method.lines + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// let mut stdin = stdin.lock(); + /// let mut buffer = String::new(); + /// + /// while stdin.read_line(&mut buffer).unwrap() > 0 { + /// // work with buffer + /// println!("{:?}", buffer); + /// + /// buffer.clear(); + /// } + /// ``` + fn read_line(&mut self, buf: &mut String) -> Result { + // Note that we are not calling the `.read_until` method here, but + // rather our hardcoded implementation. For more details as to why, see + // the comments in `read_to_end`. + append_to_string(buf, |b| read_until(self, b'\n', b)) + } + + /// Returns an iterator over the contents of this reader split on the byte + /// `byte`. + /// + /// The iterator returned from this function will return instances of + /// `io::Result>`. Each vector returned will *not* have the + /// delimiter byte at the end. + /// + /// This function will yield errors whenever `read_until` would have also + /// yielded an error. + /// + /// # Examples + /// + /// A locked standard input implements `BufRead`. In this example, we'll + /// read some input from standard input, splitting on commas. + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// + /// for content in stdin.lock().split(b',') { + /// println!("{:?}", content.unwrap()); + /// } + /// ``` + fn split(self, byte: u8) -> Split where Self: Sized { + Split { buf: self, delim: byte } + } + + /// Returns an iterator over the lines of this reader. + /// + /// The iterator returned from this function will yield instances of + /// `io::Result`. Each string returned will *not* have a newline + /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end. + /// + /// # Examples + /// + /// A locked standard input implements `BufRead`: + /// + /// ``` + /// use std::io; + /// use std::io::prelude::*; + /// + /// let stdin = io::stdin(); + /// + /// for line in stdin.lock().lines() { + /// println!("{}", line.unwrap()); + /// } + /// ``` + fn lines(self) -> Lines where Self: Sized { + Lines { buf: self } + } +} + +/// Adaptor to chain together two readers. +/// +/// This struct is generally created by calling [`chain()`][chain] on a reader. +/// Please see the documentation of `chain()` for more details. +/// +/// [chain]: trait.Read.html#method.chain +pub struct Chain { + first: T, + second: U, + done_first: bool, +} + +impl Read for Chain { + fn read(&mut self, buf: &mut [u8]) -> Result { + if !self.done_first { + match self.first.read(buf)? { + 0 => { self.done_first = true; } + n => return Ok(n), + } + } + self.second.read(buf) + } +} + + +impl BufRead for Chain { + fn fill_buf(&mut self) -> Result<&[u8]> { + if !self.done_first { + match self.first.fill_buf()? { + buf if buf.len() == 0 => { self.done_first = true; } + buf => return Ok(buf), + } + } + self.second.fill_buf() + } + + fn consume(&mut self, amt: usize) { + if !self.done_first { + self.first.consume(amt) + } else { + self.second.consume(amt) + } + } +} + +/// Reader adaptor which limits the bytes read from an underlying reader. +/// +/// This struct is generally created by calling [`take()`][take] on a reader. +/// Please see the documentation of `take()` for more details. +/// +/// [take]: trait.Read.html#method.take +pub struct Take { + inner: T, + limit: u64, +} + +impl Take { + /// Returns the number of bytes that can be read before this instance will + /// return EOF. + /// + /// # Note + /// + /// This instance may reach EOF after reading fewer bytes than indicated by + /// this method if the underlying `Read` instance reaches EOF. + pub fn limit(&self) -> u64 { self.limit } +} + +impl Read for Take { + fn read(&mut self, buf: &mut [u8]) -> Result { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(0); + } + + let max = cmp::min(buf.len() as u64, self.limit) as usize; + let n = self.inner.read(&mut buf[..max])?; + self.limit -= n as u64; + Ok(n) + } +} + + +impl BufRead for Take { + fn fill_buf(&mut self) -> Result<&[u8]> { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(&[]); + } + + let buf = self.inner.fill_buf()?; + let cap = cmp::min(buf.len() as u64, self.limit) as usize; + Ok(&buf[..cap]) + } + + fn consume(&mut self, amt: usize) { + // Don't let callers reset the limit by passing an overlarge value + let amt = cmp::min(amt as u64, self.limit) as usize; + self.limit -= amt as u64; + self.inner.consume(amt); + } +} + +/// An iterator over `u8` values of a reader. +/// +/// This struct is generally created by calling [`bytes()`][bytes] on a reader. +/// Please see the documentation of `bytes()` for more details. +/// +/// [bytes]: trait.Read.html#method.bytes +pub struct Bytes { + inner: R, +} + +impl Iterator for Bytes { + type Item = Result; + + fn next(&mut self) -> Option> { + let mut buf = [0]; + match self.inner.read(&mut buf) { + Ok(0) => None, + Ok(..) => Some(Ok(buf[0])), + Err(e) => Some(Err(e)), + } + } +} + +/// An iterator over the `char`s of a reader. +/// +/// This struct is generally created by calling [`chars()`][chars] on a reader. +/// Please see the documentation of `chars()` for more details. +/// +/// [chars]: trait.Read.html#method.chars +pub struct Chars { + inner: R, +} + +/// An enumeration of possible errors that can be generated from the `Chars` +/// adapter. +#[derive(Debug)] +pub enum CharsError { + /// Variant representing that the underlying stream was read successfully + /// but it did not contain valid utf8 data. + NotUtf8, + + /// Variant representing that an I/O error occurred. + Other(Error), +} + +impl Iterator for Chars { + type Item = result::Result; + + fn next(&mut self) -> Option> { + let mut buf = [0]; + let first_byte = match self.inner.read(&mut buf) { + Ok(0) => return None, + Ok(..) => buf[0], + Err(e) => return Some(Err(CharsError::Other(e))), + }; + let width = core_str::utf8_char_width(first_byte); + if width == 1 { return Some(Ok(first_byte as char)) } + if width == 0 { return Some(Err(CharsError::NotUtf8)) } + let mut buf = [first_byte, 0, 0, 0]; + { + let mut start = 1; + while start < width { + match self.inner.read(&mut buf[start..width]) { + Ok(0) => return Some(Err(CharsError::NotUtf8)), + Ok(n) => start += n, + Err(e) => return Some(Err(CharsError::Other(e))), + } + } + } + Some(match str::from_utf8(&buf[..width]).ok() { + Some(s) => Ok(s.chars().next().unwrap()), + None => Err(CharsError::NotUtf8), + }) + } +} + +impl fmt::Display for CharsError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + CharsError::NotUtf8 => { + "byte stream did not contain valid utf8".fmt(f) + } + CharsError::Other(ref e) => e.fmt(f), + } + } +} + +/// An iterator over the contents of an instance of `BufRead` split on a +/// particular byte. +/// +/// This struct is generally created by calling [`split()`][split] on a +/// `BufRead`. Please see the documentation of `split()` for more details. +/// +/// [split]: trait.BufRead.html#method.split + +pub struct Split { + buf: B, + delim: u8, +} + + +impl Iterator for Split { + type Item = Result>; + + fn next(&mut self) -> Option>> { + let mut buf = Vec::new(); + match self.buf.read_until(self.delim, &mut buf) { + Ok(0) => None, + Ok(_n) => { + if buf[buf.len() - 1] == self.delim { + buf.pop(); + } + Some(Ok(buf)) + } + Err(e) => Some(Err(e)) + } + } +} + +/// An iterator over the lines of an instance of `BufRead`. +/// +/// This struct is generally created by calling [`lines()`][lines] on a +/// `BufRead`. Please see the documentation of `lines()` for more details. +/// +/// [lines]: trait.BufRead.html#method.lines + +pub struct Lines { + buf: B, +} + + +impl Iterator for Lines { + type Item = Result; + + fn next(&mut self) -> Option> { + let mut buf = String::new(); + match self.buf.read_line(&mut buf) { + Ok(0) => None, + Ok(_n) => { + if buf.ends_with("\n") { + buf.pop(); + if buf.ends_with("\r") { + buf.pop(); + } + } + Some(Ok(buf)) + } + Err(e) => Some(Err(e)) + } + } +} + +#[cfg(test)] +mod tests { + use prelude::v1::*; + use io::prelude::*; + use io; + use super::Cursor; + use test; + use super::repeat; + + #[test] + fn read_until() { + let mut buf = Cursor::new(&b"12"[..]); + let mut v = Vec::new(); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2); + assert_eq!(v, b"12"); + + let mut buf = Cursor::new(&b"1233"[..]); + let mut v = Vec::new(); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3); + assert_eq!(v, b"123"); + v.truncate(0); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1); + assert_eq!(v, b"3"); + v.truncate(0); + assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0); + assert_eq!(v, []); + } + + #[test] + fn split() { + let buf = Cursor::new(&b"12"[..]); + let mut s = buf.split(b'3'); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert!(s.next().is_none()); + + let buf = Cursor::new(&b"1233"[..]); + let mut s = buf.split(b'3'); + assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']); + assert_eq!(s.next().unwrap().unwrap(), vec![]); + assert!(s.next().is_none()); + } + + #[test] + fn read_line() { + let mut buf = Cursor::new(&b"12"[..]); + let mut v = String::new(); + assert_eq!(buf.read_line(&mut v).unwrap(), 2); + assert_eq!(v, "12"); + + let mut buf = Cursor::new(&b"12\n\n"[..]); + let mut v = String::new(); + assert_eq!(buf.read_line(&mut v).unwrap(), 3); + assert_eq!(v, "12\n"); + v.truncate(0); + assert_eq!(buf.read_line(&mut v).unwrap(), 1); + assert_eq!(v, "\n"); + v.truncate(0); + assert_eq!(buf.read_line(&mut v).unwrap(), 0); + assert_eq!(v, ""); + } + + #[test] + fn lines() { + let buf = Cursor::new(&b"12\r"[..]); + let mut s = buf.lines(); + assert_eq!(s.next().unwrap().unwrap(), "12\r".to_string()); + assert!(s.next().is_none()); + + let buf = Cursor::new(&b"12\r\n\n"[..]); + let mut s = buf.lines(); + assert_eq!(s.next().unwrap().unwrap(), "12".to_string()); + assert_eq!(s.next().unwrap().unwrap(), "".to_string()); + assert!(s.next().is_none()); + } + + #[test] + fn read_to_end() { + let mut c = Cursor::new(&b""[..]); + let mut v = Vec::new(); + assert_eq!(c.read_to_end(&mut v).unwrap(), 0); + assert_eq!(v, []); + + let mut c = Cursor::new(&b"1"[..]); + let mut v = Vec::new(); + assert_eq!(c.read_to_end(&mut v).unwrap(), 1); + assert_eq!(v, b"1"); + + let cap = 1024 * 1024; + let data = (0..cap).map(|i| (i / 3) as u8).collect::>(); + let mut v = Vec::new(); + let (a, b) = data.split_at(data.len() / 2); + assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len()); + assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len()); + assert_eq!(v, data); + } + + #[test] + fn read_to_string() { + let mut c = Cursor::new(&b""[..]); + let mut v = String::new(); + assert_eq!(c.read_to_string(&mut v).unwrap(), 0); + assert_eq!(v, ""); + + let mut c = Cursor::new(&b"1"[..]); + let mut v = String::new(); + assert_eq!(c.read_to_string(&mut v).unwrap(), 1); + assert_eq!(v, "1"); + + let mut c = Cursor::new(&b"\xff"[..]); + let mut v = String::new(); + assert!(c.read_to_string(&mut v).is_err()); + } + + #[test] + fn read_exact() { + let mut buf = [0; 4]; + + let mut c = Cursor::new(&b""[..]); + assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof); + + let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..])); + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"1234"); + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"5678"); + assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof); + } + + #[test] + fn read_exact_slice() { + let mut buf = [0; 4]; + + let mut c = &b""[..]; + assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof); + + let mut c = &b"123"[..]; + assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof); + // make sure the optimized (early returning) method is being used + assert_eq!(&buf, &[0; 4]); + + let mut c = &b"1234"[..]; + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"1234"); + + let mut c = &b"56789"[..]; + c.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, b"5678"); + assert_eq!(c, b"9"); + } + + #[test] + fn take_eof() { + struct R; + + impl Read for R { + fn read(&mut self, _: &mut [u8]) -> io::Result { + Err(io::Error::new(io::ErrorKind::Other, "")) + } + } + impl BufRead for R { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + Err(io::Error::new(io::ErrorKind::Other, "")) + } + fn consume(&mut self, _amt: usize) { } + } + + let mut buf = [0; 1]; + assert_eq!(0, R.take(0).read(&mut buf).unwrap()); + assert_eq!(b"", R.take(0).fill_buf().unwrap()); + } + + fn cmp_bufread(mut br1: Br1, mut br2: Br2, exp: &[u8]) { + let mut cat = Vec::new(); + loop { + let consume = { + let buf1 = br1.fill_buf().unwrap(); + let buf2 = br2.fill_buf().unwrap(); + let minlen = if buf1.len() < buf2.len() { buf1.len() } else { buf2.len() }; + assert_eq!(buf1[..minlen], buf2[..minlen]); + cat.extend_from_slice(&buf1[..minlen]); + minlen + }; + if consume == 0 { + break; + } + br1.consume(consume); + br2.consume(consume); + } + assert_eq!(br1.fill_buf().unwrap().len(), 0); + assert_eq!(br2.fill_buf().unwrap().len(), 0); + assert_eq!(&cat[..], &exp[..]) + } + + #[test] + fn chain_bufread() { + let testdata = b"ABCDEFGHIJKL"; + let chain1 = (&testdata[..3]).chain(&testdata[3..6]) + .chain(&testdata[6..9]) + .chain(&testdata[9..]); + let chain2 = (&testdata[..4]).chain(&testdata[4..8]) + .chain(&testdata[8..]); + cmp_bufread(chain1, chain2, &testdata[..]); + } + + #[bench] + fn bench_read_to_end(b: &mut test::Bencher) { + b.iter(|| { + let mut lr = repeat(1).take(10000000); + let mut vec = Vec::with_capacity(1024); + super::read_to_end(&mut lr, &mut vec) + }); + } +} diff --git a/artiq/runtime.rs/libstd_artiq/io/prelude.rs b/artiq/runtime.rs/libstd_artiq/io/prelude.rs new file mode 100644 index 000000000..eae5acf07 --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/prelude.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The I/O Prelude +//! +//! The purpose of this module is to alleviate imports of many common I/O traits +//! by adding a glob import to the top of I/O heavy modules: +//! +//! ``` +//! # #![allow(unused_imports)] +//! use std::io::prelude::*; +//! ``` + +pub use super::{Read, Write, Seek}; + pub use super::BufRead; + + pub use alloc::boxed::Box; + pub use collections::vec::Vec; diff --git a/artiq/runtime.rs/libstd_artiq/io/util.rs b/artiq/runtime.rs/libstd_artiq/io/util.rs new file mode 100644 index 000000000..b3c2d45fd --- /dev/null +++ b/artiq/runtime.rs/libstd_artiq/io/util.rs @@ -0,0 +1,208 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(missing_copy_implementations)] + +use io::{self, Read, Write, ErrorKind}; + use io::BufRead; + +/// Copies the entire contents of a reader into a writer. +/// +/// This function will continuously read data from `reader` and then +/// write it into `writer` in a streaming fashion until `reader` +/// returns EOF. +/// +/// On success, the total number of bytes that were copied from +/// `reader` to `writer` is returned. +/// +/// # Errors +/// +/// This function will return an error immediately if any call to `read` or +/// `write` returns an error. All instances of `ErrorKind::Interrupted` are +/// handled by this function and the underlying operation is retried. +/// +/// # Examples +/// +/// ``` +/// use std::io; +/// +/// # fn foo() -> io::Result<()> { +/// let mut reader: &[u8] = b"hello"; +/// let mut writer: Vec = vec![]; +/// +/// try!(io::copy(&mut reader, &mut writer)); +/// +/// assert_eq!(reader, &writer[..]); +/// # Ok(()) +/// # } +/// ``` +pub fn copy(reader: &mut R, writer: &mut W) -> io::Result + where R: Read, W: Write +{ + let mut buf = [0; super::DEFAULT_BUF_SIZE]; + let mut written = 0; + loop { + let len = match reader.read(&mut buf) { + Ok(0) => return Ok(written), + Ok(len) => len, + Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + }; + writer.write_all(&buf[..len])?; + written += len as u64; + } +} + +/// A reader which is always at EOF. +/// +/// This struct is generally created by calling [`empty()`][empty]. Please see +/// the documentation of `empty()` for more details. +/// +/// [empty]: fn.empty.html +pub struct Empty { _priv: () } + +/// Constructs a new handle to an empty reader. +/// +/// All reads from the returned reader will return `Ok(0)`. +/// +/// # Examples +/// +/// A slightly sad example of not reading anything into a buffer: +/// +/// ``` +/// use std::io::{self, Read}; +/// +/// let mut buffer = String::new(); +/// io::empty().read_to_string(&mut buffer).unwrap(); +/// assert!(buffer.is_empty()); +/// ``` +pub fn empty() -> Empty { Empty { _priv: () } } + +impl Read for Empty { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { Ok(0) } +} + +impl BufRead for Empty { + fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + fn consume(&mut self, _n: usize) {} +} + +/// A reader which yields one byte over and over and over and over and over and... +/// +/// This struct is generally created by calling [`repeat()`][repeat]. Please +/// see the documentation of `repeat()` for more details. +/// +/// [repeat]: fn.repeat.html +pub struct Repeat { byte: u8 } + +/// Creates an instance of a reader that infinitely repeats one byte. +/// +/// All reads from this reader will succeed by filling the specified buffer with +/// the given byte. +/// +/// # Examples +/// +/// ``` +/// use std::io::{self, Read}; +/// +/// let mut buffer = [0; 3]; +/// io::repeat(0b101).read_exact(&mut buffer).unwrap(); +/// assert_eq!(buffer, [0b101, 0b101, 0b101]); +/// ``` +pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } + +impl Read for Repeat { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + for slot in &mut *buf { + *slot = self.byte; + } + Ok(buf.len()) + } +} + +/// A writer which will move data into the void. +/// +/// This struct is generally created by calling [`sink()`][sink]. Please +/// see the documentation of `sink()` for more details. +/// +/// [sink]: fn.sink.html +pub struct Sink { _priv: () } + +/// Creates an instance of a writer which will successfully consume all data. +/// +/// All calls to `write` on the returned instance will return `Ok(buf.len())` +/// and the contents of the buffer will not be inspected. +/// +/// # Examples +/// +/// ```rust +/// use std::io::{self, Write}; +/// +/// let mut buffer = vec![1, 2, 3, 5, 8]; +/// let num_bytes = io::sink().write(&mut buffer).unwrap(); +/// assert_eq!(num_bytes, 5); +/// ``` +pub fn sink() -> Sink { Sink { _priv: () } } + +impl Write for Sink { + fn write(&mut self, buf: &[u8]) -> io::Result { Ok(buf.len()) } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(test)] +mod tests { + use prelude::v1::*; + + use io::prelude::*; + use io::{copy, sink, empty, repeat}; + + #[test] + fn copy_copies() { + let mut r = repeat(0).take(4); + let mut w = sink(); + assert_eq!(copy(&mut r, &mut w).unwrap(), 4); + + let mut r = repeat(0).take(1 << 17); + assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17); + } + + #[test] + fn sink_sinks() { + let mut s = sink(); + assert_eq!(s.write(&[]).unwrap(), 0); + assert_eq!(s.write(&[0]).unwrap(), 1); + assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); + assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); + } + + #[test] + fn empty_reads() { + let mut e = empty(); + assert_eq!(e.read(&mut []).unwrap(), 0); + assert_eq!(e.read(&mut [0]).unwrap(), 0); + assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); + assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); + } + + #[test] + fn repeat_repeats() { + let mut r = repeat(4); + let mut b = [0; 1024]; + assert_eq!(r.read(&mut b).unwrap(), 1024); + assert!(b.iter().all(|b| *b == 4)); + } + + #[test] + fn take_some_bytes() { + assert_eq!(repeat(4).take(100).bytes().count(), 100); + assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); + assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); + } +} diff --git a/artiq/runtime.rs/libstd_artiq/lib.rs b/artiq/runtime.rs/libstd_artiq/lib.rs index b9ddea792..5c4abf384 100644 --- a/artiq/runtime.rs/libstd_artiq/lib.rs +++ b/artiq/runtime.rs/libstd_artiq/lib.rs @@ -1,9 +1,12 @@ -#![feature(lang_items, asm, alloc, collections, libc, needs_panic_runtime)] +#![feature(lang_items, asm, alloc, collections, libc, needs_panic_runtime, + question_mark, unicode)] #![no_std] #![needs_panic_runtime] +extern crate rustc_unicode; extern crate alloc_artiq; extern crate alloc; +#[macro_use] extern crate collections; extern crate libc; @@ -18,10 +21,13 @@ pub mod prelude { pub mod v1 { pub use core::prelude::v1::*; pub use collections::*; + pub use io::{Read, Write, Seek}; + pub use io::BufRead; } } pub mod time; +pub mod io; use core::fmt::Write;