rust/src/libstd/io/mem.rs

766 lines
21 KiB
Rust
Raw Normal View History

// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
2014-07-21 17:57:14 -05:00
//
// ignore-lexer-test FIXME #15679
//! Readers and Writers for in-memory buffers
#![allow(deprecated)]
use cmp::min;
use option::Option::None;
use result::Result::{Err, Ok};
use io;
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
2015-01-03 21:42:21 -06:00
use slice::{self, AsSlice, SliceExt};
2014-03-27 00:46:25 -05:00
use vec::Vec;
2014-10-25 20:33:56 -05:00
const BUF_CAPACITY: uint = 128;
remove seek from std::io::MemWriter, add SeekableMemWriter to librustc Not all users of MemWriter need to seek, but having MemWriter seekable adds between 3-29% in overhead in certain circumstances. This fixes that performance gap by making a non-seekable MemWriter, and creating a new SeekableMemWriter for those circumstances when that functionality is actually needed. ``` test io::mem::test::bench_buf_reader ... bench: 682 ns/iter (+/- 85) test io::mem::test::bench_buf_writer ... bench: 580 ns/iter (+/- 57) test io::mem::test::bench_mem_reader ... bench: 793 ns/iter (+/- 99) test io::mem::test::bench_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 27) test io::mem::test::bench_mem_writer_001_0010 ... bench: 65 ns/iter (+/- 27) = 153 MB/s test io::mem::test::bench_mem_writer_001_0100 ... bench: 132 ns/iter (+/- 12) = 757 MB/s test io::mem::test::bench_mem_writer_001_1000 ... bench: 802 ns/iter (+/- 151) = 1246 MB/s test io::mem::test::bench_mem_writer_100_0000 ... bench: 481 ns/iter (+/- 28) test io::mem::test::bench_mem_writer_100_0010 ... bench: 1957 ns/iter (+/- 126) = 510 MB/s test io::mem::test::bench_mem_writer_100_0100 ... bench: 8222 ns/iter (+/- 434) = 1216 MB/s test io::mem::test::bench_mem_writer_100_1000 ... bench: 82496 ns/iter (+/- 11191) = 1212 MB/s test io::mem::test::bench_seekable_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 2) test io::mem::test::bench_seekable_mem_writer_001_0010 ... bench: 64 ns/iter (+/- 2) = 156 MB/s test io::mem::test::bench_seekable_mem_writer_001_0100 ... bench: 129 ns/iter (+/- 7) = 775 MB/s test io::mem::test::bench_seekable_mem_writer_001_1000 ... bench: 801 ns/iter (+/- 159) = 1248 MB/s test io::mem::test::bench_seekable_mem_writer_100_0000 ... bench: 711 ns/iter (+/- 51) test io::mem::test::bench_seekable_mem_writer_100_0010 ... bench: 2532 ns/iter (+/- 227) = 394 MB/s test io::mem::test::bench_seekable_mem_writer_100_0100 ... bench: 8962 ns/iter (+/- 947) = 1115 MB/s test io::mem::test::bench_seekable_mem_writer_100_1000 ... bench: 85086 ns/iter (+/- 11555) = 1175 MB/s ``` [breaking-change]
2014-07-29 18:31:39 -05:00
fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
// compute offset as signed and clamp to prevent overflow
let pos = match seek {
io::SeekSet => 0,
io::SeekEnd => end,
io::SeekCur => cur,
} as i64;
if offset + pos < 0 {
Err(IoError {
kind: io::InvalidInput,
desc: "invalid seek to a negative offset",
detail: None
})
} else {
Ok((offset + pos) as u64)
}
}
impl Writer for Vec<u8> {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.push_all(buf);
Ok(())
}
}
/// Writes to an owned, growable byte vector
///
/// # Example
///
/// ```rust
/// # #![allow(unused_must_use)]
/// use std::io::MemWriter;
///
/// let mut w = MemWriter::new();
2014-11-17 02:39:01 -06:00
/// w.write(&[0, 1, 2]);
///
/// assert_eq!(w.into_inner(), vec!(0, 1, 2));
/// ```
#[deprecated = "use the Vec<u8> Writer implementation directly"]
2014-07-29 18:32:07 -05:00
#[deriving(Clone)]
pub struct MemWriter {
2014-03-27 00:46:25 -05:00
buf: Vec<u8>,
}
impl MemWriter {
/// Create a new `MemWriter`.
#[inline]
2013-10-21 19:11:42 -05:00
pub fn new() -> MemWriter {
remove seek from std::io::MemWriter, add SeekableMemWriter to librustc Not all users of MemWriter need to seek, but having MemWriter seekable adds between 3-29% in overhead in certain circumstances. This fixes that performance gap by making a non-seekable MemWriter, and creating a new SeekableMemWriter for those circumstances when that functionality is actually needed. ``` test io::mem::test::bench_buf_reader ... bench: 682 ns/iter (+/- 85) test io::mem::test::bench_buf_writer ... bench: 580 ns/iter (+/- 57) test io::mem::test::bench_mem_reader ... bench: 793 ns/iter (+/- 99) test io::mem::test::bench_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 27) test io::mem::test::bench_mem_writer_001_0010 ... bench: 65 ns/iter (+/- 27) = 153 MB/s test io::mem::test::bench_mem_writer_001_0100 ... bench: 132 ns/iter (+/- 12) = 757 MB/s test io::mem::test::bench_mem_writer_001_1000 ... bench: 802 ns/iter (+/- 151) = 1246 MB/s test io::mem::test::bench_mem_writer_100_0000 ... bench: 481 ns/iter (+/- 28) test io::mem::test::bench_mem_writer_100_0010 ... bench: 1957 ns/iter (+/- 126) = 510 MB/s test io::mem::test::bench_mem_writer_100_0100 ... bench: 8222 ns/iter (+/- 434) = 1216 MB/s test io::mem::test::bench_mem_writer_100_1000 ... bench: 82496 ns/iter (+/- 11191) = 1212 MB/s test io::mem::test::bench_seekable_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 2) test io::mem::test::bench_seekable_mem_writer_001_0010 ... bench: 64 ns/iter (+/- 2) = 156 MB/s test io::mem::test::bench_seekable_mem_writer_001_0100 ... bench: 129 ns/iter (+/- 7) = 775 MB/s test io::mem::test::bench_seekable_mem_writer_001_1000 ... bench: 801 ns/iter (+/- 159) = 1248 MB/s test io::mem::test::bench_seekable_mem_writer_100_0000 ... bench: 711 ns/iter (+/- 51) test io::mem::test::bench_seekable_mem_writer_100_0010 ... bench: 2532 ns/iter (+/- 227) = 394 MB/s test io::mem::test::bench_seekable_mem_writer_100_0100 ... bench: 8962 ns/iter (+/- 947) = 1115 MB/s test io::mem::test::bench_seekable_mem_writer_100_1000 ... bench: 85086 ns/iter (+/- 11555) = 1175 MB/s ``` [breaking-change]
2014-07-29 18:31:39 -05:00
MemWriter::with_capacity(BUF_CAPACITY)
}
/// Create a new `MemWriter`, allocating at least `n` bytes for
/// the internal buffer.
#[inline]
pub fn with_capacity(n: uint) -> MemWriter {
2014-10-25 20:33:56 -05:00
MemWriter::from_vec(Vec::with_capacity(n))
}
/// Create a new `MemWriter` that will append to an existing `Vec`.
#[inline]
pub fn from_vec(buf: Vec<u8>) -> MemWriter {
MemWriter { buf: buf }
2013-10-21 19:11:42 -05:00
}
/// Acquires an immutable reference to the underlying buffer of this
/// `MemWriter`.
#[inline]
pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
/// Unwraps this `MemWriter`, returning the underlying buffer
#[inline]
pub fn into_inner(self) -> Vec<u8> { self.buf }
/// Deprecated, use into_inner() instead
#[deprecated = "renamed to into_inner()"]
pub fn unwrap(self) -> Vec<u8> { self.into_inner() }
}
impl Writer for MemWriter {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
remove seek from std::io::MemWriter, add SeekableMemWriter to librustc Not all users of MemWriter need to seek, but having MemWriter seekable adds between 3-29% in overhead in certain circumstances. This fixes that performance gap by making a non-seekable MemWriter, and creating a new SeekableMemWriter for those circumstances when that functionality is actually needed. ``` test io::mem::test::bench_buf_reader ... bench: 682 ns/iter (+/- 85) test io::mem::test::bench_buf_writer ... bench: 580 ns/iter (+/- 57) test io::mem::test::bench_mem_reader ... bench: 793 ns/iter (+/- 99) test io::mem::test::bench_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 27) test io::mem::test::bench_mem_writer_001_0010 ... bench: 65 ns/iter (+/- 27) = 153 MB/s test io::mem::test::bench_mem_writer_001_0100 ... bench: 132 ns/iter (+/- 12) = 757 MB/s test io::mem::test::bench_mem_writer_001_1000 ... bench: 802 ns/iter (+/- 151) = 1246 MB/s test io::mem::test::bench_mem_writer_100_0000 ... bench: 481 ns/iter (+/- 28) test io::mem::test::bench_mem_writer_100_0010 ... bench: 1957 ns/iter (+/- 126) = 510 MB/s test io::mem::test::bench_mem_writer_100_0100 ... bench: 8222 ns/iter (+/- 434) = 1216 MB/s test io::mem::test::bench_mem_writer_100_1000 ... bench: 82496 ns/iter (+/- 11191) = 1212 MB/s test io::mem::test::bench_seekable_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 2) test io::mem::test::bench_seekable_mem_writer_001_0010 ... bench: 64 ns/iter (+/- 2) = 156 MB/s test io::mem::test::bench_seekable_mem_writer_001_0100 ... bench: 129 ns/iter (+/- 7) = 775 MB/s test io::mem::test::bench_seekable_mem_writer_001_1000 ... bench: 801 ns/iter (+/- 159) = 1248 MB/s test io::mem::test::bench_seekable_mem_writer_100_0000 ... bench: 711 ns/iter (+/- 51) test io::mem::test::bench_seekable_mem_writer_100_0010 ... bench: 2532 ns/iter (+/- 227) = 394 MB/s test io::mem::test::bench_seekable_mem_writer_100_0100 ... bench: 8962 ns/iter (+/- 947) = 1115 MB/s test io::mem::test::bench_seekable_mem_writer_100_1000 ... bench: 85086 ns/iter (+/- 11555) = 1175 MB/s ``` [breaking-change]
2014-07-29 18:31:39 -05:00
self.buf.push_all(buf);
Ok(())
}
2013-10-21 19:11:42 -05:00
}
2013-04-19 14:04:19 -05:00
/// Reads from an owned byte vector
///
/// # Example
///
/// ```rust
/// # #![allow(unused_must_use)]
/// use std::io::MemReader;
///
2014-03-27 00:46:25 -05:00
/// let mut r = MemReader::new(vec!(0, 1, 2));
///
/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2));
/// ```
pub struct MemReader {
2014-03-27 00:46:25 -05:00
buf: Vec<u8>,
2014-03-27 17:09:47 -05:00
pos: uint
}
impl MemReader {
/// Creates a new `MemReader` which will read the buffer given. The buffer
/// can be re-acquired through `unwrap`
#[inline]
2014-03-27 00:46:25 -05:00
pub fn new(buf: Vec<u8>) -> MemReader {
MemReader {
buf: buf,
pos: 0
}
}
/// Tests whether this reader has read all bytes in its buffer.
///
/// If `true`, then this will no longer return bytes from `read`.
#[inline]
pub fn eof(&self) -> bool { self.pos >= self.buf.len() }
/// Acquires an immutable reference to the underlying buffer of this
/// `MemReader`.
///
/// No method is exposed for acquiring a mutable reference to the buffer
/// because it could corrupt the state of this `MemReader`.
#[inline]
pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
/// Unwraps this `MemReader`, returning the underlying buffer
#[inline]
pub fn into_inner(self) -> Vec<u8> { self.buf }
/// Deprecated, use into_inner() instead
#[deprecated = "renamed to into_inner()"]
pub fn unwrap(self) -> Vec<u8> { self.into_inner() }
}
impl Reader for MemReader {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
if self.eof() { return Err(io::standard_error(io::EndOfFile)) }
let write_len = min(buf.len(), self.buf.len() - self.pos);
{
let input = self.buf[self.pos.. self.pos + write_len];
2014-12-18 17:44:24 -06:00
let output = buf.slice_to_mut(write_len);
assert_eq!(input.len(), output.len());
slice::bytes::copy_memory(output, input);
}
self.pos += write_len;
assert!(self.pos <= self.buf.len());
return Ok(write_len);
}
}
impl Seek for MemReader {
#[inline]
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
#[inline]
fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
let new = try!(combine(style, self.pos, self.buf.len(), pos));
self.pos = new as uint;
Ok(())
}
}
impl Buffer for MemReader {
#[inline]
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
if self.pos < self.buf.len() {
Ok(self.buf[self.pos..])
} else {
Err(io::standard_error(io::EndOfFile))
}
}
#[inline]
fn consume(&mut self, amt: uint) { self.pos += amt; }
}
2014-11-30 18:55:53 -06:00
impl<'a> Reader for &'a [u8] {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
if self.is_empty() { return Err(io::standard_error(io::EndOfFile)); }
let write_len = min(buf.len(), self.len());
{
let input = self[..write_len];
2014-12-18 17:44:24 -06:00
let output = buf.slice_to_mut(write_len);
2014-11-30 18:55:53 -06:00
slice::bytes::copy_memory(output, input);
}
*self = self.slice_from(write_len);
Ok(write_len)
}
}
impl<'a> Buffer for &'a [u8] {
#[inline]
2014-12-12 10:09:32 -06:00
fn fill_buf(&mut self) -> IoResult<&[u8]> {
2014-11-30 18:55:53 -06:00
if self.is_empty() {
Err(io::standard_error(io::EndOfFile))
} else {
Ok(*self)
}
}
#[inline]
fn consume(&mut self, amt: uint) {
*self = self[amt..];
}
}
/// Writes to a fixed-size byte slice
///
/// If a write will not fit in the buffer, it returns an error and does not
/// write any data.
///
/// # Example
///
/// ```rust
/// # #![allow(unused_must_use)]
/// use std::io::BufWriter;
///
/// let mut buf = [0; 4];
/// {
2014-11-17 02:39:01 -06:00
/// let mut w = BufWriter::new(&mut buf);
/// w.write(&[0, 1, 2]);
/// }
/// assert!(buf == [0, 1, 2, 0]);
/// ```
pub struct BufWriter<'a> {
2014-03-27 17:09:47 -05:00
buf: &'a mut [u8],
pos: uint
}
2013-04-19 14:04:19 -05:00
impl<'a> BufWriter<'a> {
/// Creates a new `BufWriter` which will wrap the specified buffer. The
/// writer initially starts at position 0.
#[inline]
2014-12-12 10:09:32 -06:00
pub fn new(buf: &'a mut [u8]) -> BufWriter<'a> {
BufWriter {
buf: buf,
pos: 0
}
}
}
impl<'a> Writer for BufWriter<'a> {
#[inline]
fn write(&mut self, src: &[u8]) -> IoResult<()> {
2014-12-18 17:44:24 -06:00
let dst = self.buf.slice_from_mut(self.pos);
let dst_len = dst.len();
if dst_len == 0 {
return Err(io::standard_error(io::EndOfFile));
}
let src_len = src.len();
if dst_len >= src_len {
slice::bytes::copy_memory(dst, src);
self.pos += src_len;
Ok(())
} else {
slice::bytes::copy_memory(dst, src[..dst_len]);
self.pos += dst_len;
Err(io::standard_error(io::ShortWrite(dst_len)))
}
}
}
impl<'a> Seek for BufWriter<'a> {
#[inline]
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
#[inline]
fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
let new = try!(combine(style, self.pos, self.buf.len(), pos));
self.pos = min(new as uint, self.buf.len());
Ok(())
}
}
2013-04-19 14:04:19 -05:00
/// Reads from a fixed-size byte slice
///
/// # Example
///
/// ```rust
/// # #![allow(unused_must_use)]
/// use std::io::BufReader;
///
/// let buf = [0, 1, 2, 3];
/// let mut r = BufReader::new(&buf);
///
/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]);
/// ```
pub struct BufReader<'a> {
2014-03-27 17:09:47 -05:00
buf: &'a [u8],
pos: uint
}
impl<'a> BufReader<'a> {
/// Creates a new buffered reader which will read the specified buffer
#[inline]
2014-12-12 10:09:32 -06:00
pub fn new(buf: &'a [u8]) -> BufReader<'a> {
BufReader {
buf: buf,
pos: 0
}
}
/// Tests whether this reader has read all bytes in its buffer.
///
/// If `true`, then this will no longer return bytes from `read`.
#[inline]
pub fn eof(&self) -> bool { self.pos >= self.buf.len() }
}
impl<'a> Reader for BufReader<'a> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
if self.eof() { return Err(io::standard_error(io::EndOfFile)) }
2013-09-02 13:23:57 -05:00
let write_len = min(buf.len(), self.buf.len() - self.pos);
{
let input = self.buf[self.pos.. self.pos + write_len];
2014-12-18 17:44:24 -06:00
let output = buf.slice_to_mut(write_len);
2013-09-02 13:23:57 -05:00
assert_eq!(input.len(), output.len());
slice::bytes::copy_memory(output, input);
2013-09-02 13:23:57 -05:00
}
self.pos += write_len;
assert!(self.pos <= self.buf.len());
return Ok(write_len);
2013-09-02 13:23:57 -05:00
}
}
impl<'a> Seek for BufReader<'a> {
#[inline]
fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
#[inline]
fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
let new = try!(combine(style, self.pos, self.buf.len(), pos));
self.pos = new as uint;
Ok(())
}
}
impl<'a> Buffer for BufReader<'a> {
#[inline]
2014-12-12 10:09:32 -06:00
fn fill_buf(&mut self) -> IoResult<&[u8]> {
if self.pos < self.buf.len() {
Ok(self.buf[self.pos..])
} else {
Err(io::standard_error(io::EndOfFile))
}
}
#[inline]
fn consume(&mut self, amt: uint) { self.pos += amt; }
}
#[cfg(test)]
mod test {
extern crate "test" as test_crate;
use prelude::v1::*;
use super::*;
std: Second pass stabilization for `comm` This commit is a second pass stabilization for the `std::comm` module, performing the following actions: * The entire `std::comm` module was moved under `std::sync::mpsc`. This movement reflects that channels are just yet another synchronization primitive, and they don't necessarily deserve a special place outside of the other concurrency primitives that the standard library offers. * The `send` and `recv` methods have all been removed. * The `send_opt` and `recv_opt` methods have been renamed to `send` and `recv`. This means that all send/receive operations return a `Result` now indicating whether the operation was successful or not. * The error type of `send` is now a `SendError` to implement a custom error message and allow for `unwrap()`. The error type contains an `into_inner` method to extract the value. * The error type of `recv` is now `RecvError` for the same reasons as `send`. * The `TryRecvError` and `TrySendError` types have had public reexports removed of their variants and the variant names have been tweaked with enum namespacing rules. * The `Messages` iterator is renamed to `Iter` This functionality is now all `#[stable]`: * `Sender` * `SyncSender` * `Receiver` * `std::sync::mpsc` * `channel` * `sync_channel` * `Iter` * `Sender::send` * `Sender::clone` * `SyncSender::send` * `SyncSender::try_send` * `SyncSender::clone` * `Receiver::recv` * `Receiver::try_recv` * `Receiver::iter` * `SendError` * `RecvError` * `TrySendError::{mod, Full, Disconnected}` * `TryRecvError::{mod, Empty, Disconnected}` * `SendError::into_inner` * `TrySendError::into_inner` This is a breaking change due to the modification of where this module is located, as well as the changing of the semantics of `send` and `recv`. Most programs just need to rename imports of `std::comm` to `std::sync::mpsc` and add calls to `unwrap` after a send or a receive operation. [breaking-change]
2014-12-23 13:53:35 -06:00
use io::{SeekSet, SeekCur, SeekEnd};
2014-01-30 16:10:53 -06:00
use io;
use self::test_crate::Bencher;
#[test]
fn test_vec_writer() {
let mut writer = Vec::new();
writer.write(&[0]).unwrap();
writer.write(&[1, 2, 3]).unwrap();
writer.write(&[4, 5, 6, 7]).unwrap();
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(writer.as_slice(), b);
}
#[test]
fn test_mem_writer() {
let mut writer = MemWriter::new();
2014-11-17 02:39:01 -06:00
writer.write(&[0]).unwrap();
writer.write(&[1, 2, 3]).unwrap();
writer.write(&[4, 5, 6, 7]).unwrap();
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(writer.get_ref(), b);
}
#[test]
fn test_buf_writer() {
let mut buf = [0 as u8; 9];
{
2014-11-17 02:39:01 -06:00
let mut writer = BufWriter::new(&mut buf);
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(0));
2014-11-17 02:39:01 -06:00
writer.write(&[0]).unwrap();
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(1));
2014-11-17 02:39:01 -06:00
writer.write(&[1, 2, 3]).unwrap();
writer.write(&[4, 5, 6, 7]).unwrap();
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(8));
2014-11-17 02:39:01 -06:00
writer.write(&[]).unwrap();
assert_eq!(writer.tell(), Ok(8));
assert_eq!(writer.write(&[8, 9]).unwrap_err().kind, io::ShortWrite(1));
assert_eq!(writer.write(&[10]).unwrap_err().kind, io::EndOfFile);
}
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];
{
2014-11-17 02:39:01 -06:00
let mut writer = BufWriter::new(&mut buf);
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(0));
2014-11-17 02:39:01 -06:00
writer.write(&[1]).unwrap();
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(1));
2014-01-30 16:10:53 -06:00
writer.seek(2, SeekSet).unwrap();
assert_eq!(writer.tell(), Ok(2));
2014-11-17 02:39:01 -06:00
writer.write(&[2]).unwrap();
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(3));
2014-01-30 16:10:53 -06:00
writer.seek(-2, SeekCur).unwrap();
assert_eq!(writer.tell(), Ok(1));
2014-11-17 02:39:01 -06:00
writer.write(&[3]).unwrap();
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(2));
2014-01-30 16:10:53 -06:00
writer.seek(-1, SeekEnd).unwrap();
assert_eq!(writer.tell(), Ok(7));
2014-11-17 02:39:01 -06:00
writer.write(&[4]).unwrap();
2014-01-30 16:10:53 -06:00
assert_eq!(writer.tell(), Ok(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];
2014-11-17 02:39:01 -06:00
let mut writer = BufWriter::new(&mut buf);
writer.write(&[0]).unwrap();
2014-01-30 16:10:53 -06:00
2014-11-17 02:39:01 -06:00
match writer.write(&[0, 0]) {
Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::ShortWrite(1)),
2014-01-30 16:10:53 -06:00
}
}
#[test]
fn test_mem_reader() {
2014-03-27 00:46:25 -05:00
let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
let mut buf = [];
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(0));
2014-01-30 16:10:53 -06:00
assert_eq!(reader.tell(), Ok(0));
let mut buf = [0];
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(1));
2014-01-30 16:10:53 -06:00
assert_eq!(reader.tell(), Ok(1));
let b: &[_] = &[0];
assert_eq!(buf, b);
let mut buf = [0; 4];
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(4));
2014-01-30 16:10:53 -06:00
assert_eq!(reader.tell(), Ok(5));
let b: &[_] = &[1, 2, 3, 4];
assert_eq!(buf, b);
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(3));
let b: &[_] = &[5, 6, 7];
assert_eq!(buf[0..3], b);
2014-11-17 02:39:01 -06:00
assert!(reader.read(&mut buf).is_err());
2014-03-27 00:46:25 -05:00
let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
2014-11-17 02:39:01 -06:00
assert!(reader.read(&mut buf).is_err());
}
2013-09-02 13:23:57 -05:00
2014-11-30 18:55:53 -06:00
#[test]
fn test_slice_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
let mut reader = &mut in_buf.as_slice();
let mut buf = [];
assert_eq!(reader.read(&mut buf), Ok(0));
let mut buf = [0];
assert_eq!(reader.read(&mut buf), Ok(1));
assert_eq!(reader.len(), 7);
let b: &[_] = &[0];
assert_eq!(buf.as_slice(), b);
let mut buf = [0; 4];
2014-11-30 18:55:53 -06:00
assert_eq!(reader.read(&mut buf), Ok(4));
assert_eq!(reader.len(), 3);
let b: &[_] = &[1, 2, 3, 4];
assert_eq!(buf.as_slice(), b);
assert_eq!(reader.read(&mut buf), Ok(3));
let b: &[_] = &[5, 6, 7];
assert_eq!(buf[0..3], b);
assert!(reader.read(&mut buf).is_err());
let mut reader = &mut in_buf.as_slice();
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
assert!(reader.read(&mut buf).is_err());
}
2013-09-02 13:23:57 -05:00
#[test]
fn test_buf_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
let mut reader = BufReader::new(in_buf.as_slice());
2013-09-02 13:23:57 -05:00
let mut buf = [];
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(0));
2014-01-30 16:10:53 -06:00
assert_eq!(reader.tell(), Ok(0));
2013-09-02 13:23:57 -05:00
let mut buf = [0];
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(1));
2014-01-30 16:10:53 -06:00
assert_eq!(reader.tell(), Ok(1));
let b: &[_] = &[0];
assert_eq!(buf, b);
let mut buf = [0; 4];
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(4));
2014-01-30 16:10:53 -06:00
assert_eq!(reader.tell(), Ok(5));
let b: &[_] = &[1, 2, 3, 4];
assert_eq!(buf, b);
2014-11-17 02:39:01 -06:00
assert_eq!(reader.read(&mut buf), Ok(3));
let b: &[_] = &[5, 6, 7];
assert_eq!(buf[0..3], b);
2014-11-17 02:39:01 -06:00
assert!(reader.read(&mut buf).is_err());
let mut reader = BufReader::new(in_buf.as_slice());
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
2014-11-17 02:39:01 -06:00
assert!(reader.read(&mut buf).is_err());
2013-09-02 13:23:57 -05:00
}
#[test]
fn test_read_char() {
let b = b"Vi\xE1\xBB\x87t";
let mut r = BufReader::new(b);
2014-01-30 16:10:53 -06:00
assert_eq!(r.read_char(), Ok('V'));
assert_eq!(r.read_char(), Ok('i'));
assert_eq!(r.read_char(), Ok('ệ'));
assert_eq!(r.read_char(), Ok('t'));
assert!(r.read_char().is_err());
}
#[test]
fn test_read_bad_char() {
let b = b"\x80";
let mut r = BufReader::new(b);
2014-01-30 16:10:53 -06:00
assert!(r.read_char().is_err());
}
#[test]
fn test_write_strings() {
let mut writer = MemWriter::new();
2014-01-30 16:10:53 -06:00
writer.write_str("testing").unwrap();
writer.write_line("testing").unwrap();
writer.write_str("testing").unwrap();
let mut r = BufReader::new(writer.get_ref());
assert_eq!(r.read_to_string().unwrap(), "testingtesting\ntesting");
}
2014-01-04 07:26:03 -06:00
#[test]
fn test_write_char() {
let mut writer = MemWriter::new();
2014-01-30 16:10:53 -06:00
writer.write_char('a').unwrap();
writer.write_char('\n').unwrap();
writer.write_char('ệ').unwrap();
let mut r = BufReader::new(writer.get_ref());
assert_eq!(r.read_to_string().unwrap(), "a\n");
2014-01-04 07:26:03 -06:00
}
#[test]
fn test_read_whole_string_bad() {
let buf = [0xff];
2014-11-17 02:39:01 -06:00
let mut r = BufReader::new(&buf);
match r.read_to_string() {
Ok(..) => panic!(),
Err(..) => {}
}
}
#[test]
fn seek_past_end() {
let buf = [0xff];
2014-11-17 02:39:01 -06:00
let mut r = BufReader::new(&buf);
r.seek(10, SeekSet).unwrap();
assert!(r.read(&mut []).is_err());
2014-03-27 00:46:25 -05:00
let mut r = MemReader::new(vec!(10));
r.seek(10, SeekSet).unwrap();
assert!(r.read(&mut []).is_err());
let mut buf = [0];
2014-11-17 02:39:01 -06:00
let mut r = BufWriter::new(&mut buf);
r.seek(10, SeekSet).unwrap();
2014-11-17 02:39:01 -06:00
assert!(r.write(&[3]).is_err());
}
#[test]
fn seek_before_0() {
let buf = [0xff];
2014-11-17 02:39:01 -06:00
let mut r = BufReader::new(&buf);
assert!(r.seek(-1, SeekSet).is_err());
2014-03-27 00:46:25 -05:00
let mut r = MemReader::new(vec!(10));
assert!(r.seek(-1, SeekSet).is_err());
let mut buf = [0];
2014-11-17 02:39:01 -06:00
let mut r = BufWriter::new(&mut buf);
assert!(r.seek(-1, SeekSet).is_err());
}
#[test]
fn io_read_at_least() {
let mut r = MemReader::new(vec![1, 2, 3, 4, 5, 6, 7, 8]);
let mut buf = [0; 3];
2014-11-17 02:39:01 -06:00
assert!(r.read_at_least(buf.len(), &mut buf).is_ok());
let b: &[_] = &[1, 2, 3];
assert_eq!(buf, b);
2014-12-18 17:44:24 -06:00
assert!(r.read_at_least(0, buf.slice_to_mut(0)).is_ok());
assert_eq!(buf, b);
2014-11-17 02:39:01 -06:00
assert!(r.read_at_least(buf.len(), &mut buf).is_ok());
let b: &[_] = &[4, 5, 6];
assert_eq!(buf, b);
2014-11-17 02:39:01 -06:00
assert!(r.read_at_least(buf.len(), &mut buf).is_err());
let b: &[_] = &[7, 8, 6];
assert_eq!(buf, b);
}
2014-07-06 00:31:57 -05:00
fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) {
let src: Vec<u8> = Vec::from_elem(len, 5);
remove seek from std::io::MemWriter, add SeekableMemWriter to librustc Not all users of MemWriter need to seek, but having MemWriter seekable adds between 3-29% in overhead in certain circumstances. This fixes that performance gap by making a non-seekable MemWriter, and creating a new SeekableMemWriter for those circumstances when that functionality is actually needed. ``` test io::mem::test::bench_buf_reader ... bench: 682 ns/iter (+/- 85) test io::mem::test::bench_buf_writer ... bench: 580 ns/iter (+/- 57) test io::mem::test::bench_mem_reader ... bench: 793 ns/iter (+/- 99) test io::mem::test::bench_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 27) test io::mem::test::bench_mem_writer_001_0010 ... bench: 65 ns/iter (+/- 27) = 153 MB/s test io::mem::test::bench_mem_writer_001_0100 ... bench: 132 ns/iter (+/- 12) = 757 MB/s test io::mem::test::bench_mem_writer_001_1000 ... bench: 802 ns/iter (+/- 151) = 1246 MB/s test io::mem::test::bench_mem_writer_100_0000 ... bench: 481 ns/iter (+/- 28) test io::mem::test::bench_mem_writer_100_0010 ... bench: 1957 ns/iter (+/- 126) = 510 MB/s test io::mem::test::bench_mem_writer_100_0100 ... bench: 8222 ns/iter (+/- 434) = 1216 MB/s test io::mem::test::bench_mem_writer_100_1000 ... bench: 82496 ns/iter (+/- 11191) = 1212 MB/s test io::mem::test::bench_seekable_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 2) test io::mem::test::bench_seekable_mem_writer_001_0010 ... bench: 64 ns/iter (+/- 2) = 156 MB/s test io::mem::test::bench_seekable_mem_writer_001_0100 ... bench: 129 ns/iter (+/- 7) = 775 MB/s test io::mem::test::bench_seekable_mem_writer_001_1000 ... bench: 801 ns/iter (+/- 159) = 1248 MB/s test io::mem::test::bench_seekable_mem_writer_100_0000 ... bench: 711 ns/iter (+/- 51) test io::mem::test::bench_seekable_mem_writer_100_0010 ... bench: 2532 ns/iter (+/- 227) = 394 MB/s test io::mem::test::bench_seekable_mem_writer_100_0100 ... bench: 8962 ns/iter (+/- 947) = 1115 MB/s test io::mem::test::bench_seekable_mem_writer_100_1000 ... bench: 85086 ns/iter (+/- 11555) = 1175 MB/s ``` [breaking-change]
2014-07-29 18:31:39 -05:00
b.bytes = (times * len) as u64;
b.iter(|| {
let mut wr = MemWriter::new();
2014-07-06 00:31:57 -05:00
for _ in range(0, times) {
wr.write(src.as_slice()).unwrap();
}
2014-07-06 00:31:57 -05:00
let v = wr.unwrap();
assert_eq!(v.len(), times * len);
assert!(v.iter().all(|x| *x == 5));
});
}
2014-07-06 00:31:57 -05:00
#[bench]
fn bench_mem_writer_001_0000(b: &mut Bencher) {
do_bench_mem_writer(b, 1, 0)
}
#[bench]
fn bench_mem_writer_001_0010(b: &mut Bencher) {
do_bench_mem_writer(b, 1, 10)
}
#[bench]
fn bench_mem_writer_001_0100(b: &mut Bencher) {
do_bench_mem_writer(b, 1, 100)
}
#[bench]
fn bench_mem_writer_001_1000(b: &mut Bencher) {
do_bench_mem_writer(b, 1, 1000)
}
#[bench]
fn bench_mem_writer_100_0000(b: &mut Bencher) {
do_bench_mem_writer(b, 100, 0)
}
#[bench]
fn bench_mem_writer_100_0010(b: &mut Bencher) {
do_bench_mem_writer(b, 100, 10)
}
#[bench]
fn bench_mem_writer_100_0100(b: &mut Bencher) {
do_bench_mem_writer(b, 100, 100)
}
#[bench]
fn bench_mem_writer_100_1000(b: &mut Bencher) {
do_bench_mem_writer(b, 100, 1000)
}
#[bench]
fn bench_mem_reader(b: &mut Bencher) {
b.iter(|| {
let buf = [5 as u8; 100].to_vec();
{
let mut rdr = MemReader::new(buf);
for _i in range(0u, 10) {
2014-12-31 22:40:24 -06:00
let mut buf = [0 as u8; 10];
2014-11-17 02:39:01 -06:00
rdr.read(&mut buf).unwrap();
2014-12-31 22:40:24 -06:00
assert_eq!(buf.as_slice(), [5; 10].as_slice());
}
}
});
}
#[bench]
fn bench_buf_writer(b: &mut Bencher) {
b.iter(|| {
let mut buf = [0 as u8; 100];
{
2014-11-17 02:39:01 -06:00
let mut wr = BufWriter::new(&mut buf);
for _i in range(0u, 10) {
2014-12-31 22:40:24 -06:00
wr.write(&[5; 10]).unwrap();
}
}
2014-12-31 22:40:24 -06:00
assert_eq!(buf.as_slice(), [5; 100].as_slice());
});
}
#[bench]
fn bench_buf_reader(b: &mut Bencher) {
b.iter(|| {
let buf = [5 as u8; 100];
{
2014-11-17 02:39:01 -06:00
let mut rdr = BufReader::new(&buf);
for _i in range(0u, 10) {
2014-12-31 22:40:24 -06:00
let mut buf = [0 as u8; 10];
2014-11-17 02:39:01 -06:00
rdr.read(&mut buf).unwrap();
2014-12-31 22:40:24 -06:00
assert_eq!(buf, [5; 10]);
}
}
});
}
}