2013-12-09 22:53:09 -08:00
|
|
|
// 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-01-29 16:33:57 -08:00
|
|
|
|
2014-11-25 21:17:11 -05:00
|
|
|
//! Utility implementations of Reader and Writer
|
2014-02-23 15:48:26 -05:00
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
use prelude::*;
|
|
|
|
|
use cmp;
|
2014-01-29 16:33:57 -08:00
|
|
|
use io;
|
2014-03-08 18:11:52 -05:00
|
|
|
use slice::bytes::MutableByteVector;
|
2013-12-09 22:53:09 -08:00
|
|
|
|
|
|
|
|
/// Wraps a `Reader`, limiting the number of bytes that can be read from it.
|
2014-02-13 23:28:11 -05:00
|
|
|
pub struct LimitReader<R> {
|
2014-03-27 15:09:47 -07:00
|
|
|
limit: uint,
|
|
|
|
|
inner: R
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
2014-02-13 23:28:11 -05:00
|
|
|
impl<R: Reader> LimitReader<R> {
|
2013-12-09 22:53:09 -08:00
|
|
|
/// Creates a new `LimitReader`
|
2014-02-13 23:28:11 -05:00
|
|
|
pub fn new(r: R, limit: uint) -> LimitReader<R> {
|
2013-12-09 22:53:09 -08:00
|
|
|
LimitReader { limit: limit, inner: r }
|
|
|
|
|
}
|
2014-02-15 13:51:37 -08:00
|
|
|
|
|
|
|
|
/// Consumes the `LimitReader`, returning the underlying `Reader`.
|
2014-11-20 09:23:43 -08:00
|
|
|
pub fn into_inner(self) -> R { self.inner }
|
|
|
|
|
|
|
|
|
|
/// Deprecated, use into_inner() instead
|
|
|
|
|
#[deprecated = "renamed to into_inner"]
|
|
|
|
|
pub fn unwrap(self) -> R { self.into_inner() }
|
2014-02-15 13:51:37 -08:00
|
|
|
|
|
|
|
|
/// Returns the number of bytes that can be read before the `LimitReader`
|
|
|
|
|
/// will return EOF.
|
|
|
|
|
///
|
|
|
|
|
/// # Note
|
|
|
|
|
///
|
|
|
|
|
/// The reader may reach EOF after reading fewer bytes than indicated by
|
|
|
|
|
/// this method if the underlying reader reaches EOF.
|
|
|
|
|
pub fn limit(&self) -> uint { self.limit }
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
2014-02-13 23:28:11 -05:00
|
|
|
impl<R: Reader> Reader for LimitReader<R> {
|
2014-01-29 16:33:57 -08:00
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
2013-12-09 22:53:09 -08:00
|
|
|
if self.limit == 0 {
|
2014-01-29 16:33:57 -08:00
|
|
|
return Err(io::standard_error(io::EndOfFile));
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let len = cmp::min(self.limit, buf.len());
|
2014-09-24 23:41:09 +12:00
|
|
|
let res = self.inner.read(buf[mut ..len]);
|
2014-08-14 23:06:30 -07:00
|
|
|
match res {
|
|
|
|
|
Ok(len) => self.limit -= len,
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
res
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-05 23:50:07 -07:00
|
|
|
impl<R: Buffer> Buffer for LimitReader<R> {
|
|
|
|
|
fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
|
|
|
|
|
let amt = try!(self.inner.fill_buf());
|
2014-09-24 23:41:09 +12:00
|
|
|
let buf = amt[..cmp::min(amt.len(), self.limit)];
|
2014-05-05 23:50:07 -07:00
|
|
|
if buf.len() == 0 {
|
|
|
|
|
Err(io::standard_error(io::EndOfFile))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(buf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn consume(&mut self, amt: uint) {
|
2014-08-14 23:06:30 -07:00
|
|
|
// Don't let callers reset the limit by passing an overlarge value
|
|
|
|
|
let amt = cmp::min(amt, self.limit);
|
2014-05-05 23:50:07 -07:00
|
|
|
self.limit -= amt;
|
|
|
|
|
self.inner.consume(amt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
/// A `Writer` which ignores bytes written to it, like /dev/null.
|
|
|
|
|
pub struct NullWriter;
|
|
|
|
|
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 17:01:33 -08:00
|
|
|
impl Copy for NullWriter {}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
impl Writer for NullWriter {
|
|
|
|
|
#[inline]
|
2014-01-29 16:33:57 -08:00
|
|
|
fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> { Ok(()) }
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
|
|
|
|
|
pub struct ZeroReader;
|
|
|
|
|
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 17:01:33 -08:00
|
|
|
impl Copy for ZeroReader {}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
impl Reader for ZeroReader {
|
|
|
|
|
#[inline]
|
2014-01-29 16:33:57 -08:00
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
2013-12-09 22:53:09 -08:00
|
|
|
buf.set_memory(0);
|
2014-01-29 16:33:57 -08:00
|
|
|
Ok(buf.len())
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-05 23:50:07 -07:00
|
|
|
impl Buffer for ZeroReader {
|
|
|
|
|
fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
|
|
|
|
|
static DATA: [u8, ..64] = [0, ..64];
|
|
|
|
|
Ok(DATA.as_slice())
|
|
|
|
|
}
|
2014-08-14 23:06:30 -07:00
|
|
|
|
2014-05-05 23:50:07 -07:00
|
|
|
fn consume(&mut self, _amt: uint) {}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
/// A `Reader` which is always at EOF, like /dev/null.
|
|
|
|
|
pub struct NullReader;
|
|
|
|
|
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 17:01:33 -08:00
|
|
|
impl Copy for NullReader {}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
impl Reader for NullReader {
|
|
|
|
|
#[inline]
|
2014-01-29 16:33:57 -08:00
|
|
|
fn read(&mut self, _buf: &mut [u8]) -> io::IoResult<uint> {
|
|
|
|
|
Err(io::standard_error(io::EndOfFile))
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-05 23:50:07 -07:00
|
|
|
impl Buffer for NullReader {
|
|
|
|
|
fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
|
|
|
|
|
Err(io::standard_error(io::EndOfFile))
|
|
|
|
|
}
|
|
|
|
|
fn consume(&mut self, _amt: uint) {}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 23:06:30 -07:00
|
|
|
/// A `Writer` which multiplexes writes to a set of `Writer`s.
|
|
|
|
|
///
|
|
|
|
|
/// The `Writer`s are delegated to in order. If any `Writer` returns an error,
|
|
|
|
|
/// that error is returned immediately and remaining `Writer`s are not called.
|
2013-12-09 22:53:09 -08:00
|
|
|
pub struct MultiWriter {
|
2014-08-27 21:46:52 -04:00
|
|
|
writers: Vec<Box<Writer+'static>>
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MultiWriter {
|
|
|
|
|
/// Creates a new `MultiWriter`
|
2014-08-27 21:46:52 -04:00
|
|
|
pub fn new(writers: Vec<Box<Writer+'static>>) -> MultiWriter {
|
2013-12-09 22:53:09 -08:00
|
|
|
MultiWriter { writers: writers }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Writer for MultiWriter {
|
|
|
|
|
#[inline]
|
2014-01-29 16:33:57 -08:00
|
|
|
fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
|
2014-09-14 20:27:36 -07:00
|
|
|
for writer in self.writers.iter_mut() {
|
2014-08-14 23:06:30 -07:00
|
|
|
try!(writer.write(buf));
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
2014-08-14 23:06:30 -07:00
|
|
|
Ok(())
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2014-01-29 16:33:57 -08:00
|
|
|
fn flush(&mut self) -> io::IoResult<()> {
|
2014-09-14 20:27:36 -07:00
|
|
|
for writer in self.writers.iter_mut() {
|
2014-08-14 23:06:30 -07:00
|
|
|
try!(writer.flush());
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
2014-08-14 23:06:30 -07:00
|
|
|
Ok(())
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 23:06:30 -07:00
|
|
|
/// A `Reader` which chains input from multiple `Reader`s, reading each to
|
2013-12-09 22:53:09 -08:00
|
|
|
/// completion before moving onto the next.
|
|
|
|
|
pub struct ChainedReader<I, R> {
|
2014-03-27 15:09:47 -07:00
|
|
|
readers: I,
|
|
|
|
|
cur_reader: Option<R>,
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R: Reader, I: Iterator<R>> ChainedReader<I, R> {
|
|
|
|
|
/// Creates a new `ChainedReader`
|
|
|
|
|
pub fn new(mut readers: I) -> ChainedReader<I, R> {
|
|
|
|
|
let r = readers.next();
|
|
|
|
|
ChainedReader { readers: readers, cur_reader: r }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R: Reader, I: Iterator<R>> Reader for ChainedReader<I, R> {
|
2014-01-29 16:33:57 -08:00
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
2013-12-09 22:53:09 -08:00
|
|
|
loop {
|
2014-01-29 16:33:57 -08:00
|
|
|
let err = match self.cur_reader {
|
2013-12-09 22:53:09 -08:00
|
|
|
Some(ref mut r) => {
|
|
|
|
|
match r.read(buf) {
|
2014-01-29 16:33:57 -08:00
|
|
|
Ok(len) => return Ok(len),
|
|
|
|
|
Err(ref e) if e.kind == io::EndOfFile => None,
|
|
|
|
|
Err(e) => Some(e),
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None => break
|
2014-01-29 16:33:57 -08:00
|
|
|
};
|
|
|
|
|
self.cur_reader = self.readers.next();
|
|
|
|
|
match err {
|
|
|
|
|
Some(e) => return Err(e),
|
|
|
|
|
None => {}
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
2014-01-29 16:33:57 -08:00
|
|
|
Err(io::standard_error(io::EndOfFile))
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A `Reader` which forwards input from another `Reader`, passing it along to
|
|
|
|
|
/// a `Writer` as well. Similar to the `tee(1)` command.
|
|
|
|
|
pub struct TeeReader<R, W> {
|
2014-03-27 15:09:47 -07:00
|
|
|
reader: R,
|
|
|
|
|
writer: W,
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R: Reader, W: Writer> TeeReader<R, W> {
|
|
|
|
|
/// Creates a new `TeeReader`
|
|
|
|
|
pub fn new(r: R, w: W) -> TeeReader<R, W> {
|
|
|
|
|
TeeReader { reader: r, writer: w }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Consumes the `TeeReader`, returning the underlying `Reader` and
|
|
|
|
|
/// `Writer`.
|
2014-11-20 09:23:43 -08:00
|
|
|
pub fn into_inner(self) -> (R, W) {
|
2013-12-09 22:53:09 -08:00
|
|
|
let TeeReader { reader, writer } = self;
|
|
|
|
|
(reader, writer)
|
|
|
|
|
}
|
2014-11-20 09:23:43 -08:00
|
|
|
|
|
|
|
|
/// Deprecated, use into_inner() instead
|
|
|
|
|
#[deprecated = "renamed to into_inner"]
|
|
|
|
|
pub fn unwrap(self) -> (R, W) { self.into_inner() }
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
|
2014-01-29 16:33:57 -08:00
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
|
|
|
|
self.reader.read(buf).and_then(|len| {
|
2014-09-24 23:41:09 +12:00
|
|
|
self.writer.write(buf[mut ..len]).map(|()| len)
|
2013-12-09 22:53:09 -08:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Copies all data from a `Reader` to a `Writer`.
|
2014-01-29 16:33:57 -08:00
|
|
|
pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
|
2013-12-09 22:53:09 -08:00
|
|
|
let mut buf = [0, ..super::DEFAULT_BUF_SIZE];
|
|
|
|
|
loop {
|
2014-11-17 21:39:01 +13:00
|
|
|
let len = match r.read(&mut buf) {
|
2014-01-29 16:33:57 -08:00
|
|
|
Ok(len) => len,
|
|
|
|
|
Err(ref e) if e.kind == io::EndOfFile => return Ok(()),
|
|
|
|
|
Err(e) => return Err(e),
|
|
|
|
|
};
|
2014-09-24 23:41:09 +12:00
|
|
|
try!(w.write(buf[..len]));
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 23:06:30 -07:00
|
|
|
/// An adaptor converting an `Iterator<u8>` to a `Reader`.
|
2014-06-02 20:42:41 -07:00
|
|
|
pub struct IterReader<T> {
|
|
|
|
|
iter: T,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Iterator<u8>> IterReader<T> {
|
2014-08-14 23:06:30 -07:00
|
|
|
/// Creates a new `IterReader` which will read from the specified
|
|
|
|
|
/// `Iterator`.
|
2014-06-02 20:42:41 -07:00
|
|
|
pub fn new(iter: T) -> IterReader<T> {
|
2014-08-14 23:06:30 -07:00
|
|
|
IterReader { iter: iter }
|
2014-06-02 20:42:41 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: Iterator<u8>> Reader for IterReader<T> {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
|
|
|
|
|
let mut len = 0;
|
2014-09-14 20:27:36 -07:00
|
|
|
for (slot, elt) in buf.iter_mut().zip(self.iter.by_ref()) {
|
2014-06-02 20:42:41 -07:00
|
|
|
*slot = elt;
|
|
|
|
|
len += 1;
|
|
|
|
|
}
|
2014-08-14 23:06:30 -07:00
|
|
|
if len == 0 && buf.len() != 0 {
|
2014-06-02 20:42:41 -07:00
|
|
|
Err(io::standard_error(io::EndOfFile))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(len)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
2014-11-30 16:55:53 -08:00
|
|
|
use io::{MemReader, ByRefReader};
|
2014-01-30 14:10:53 -08:00
|
|
|
use io;
|
2014-07-10 14:19:17 -07:00
|
|
|
use boxed::Box;
|
2013-12-09 22:53:09 -08:00
|
|
|
use super::*;
|
|
|
|
|
use prelude::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
2014-02-15 13:51:37 -08:00
|
|
|
fn test_limit_reader_unlimited() {
|
2014-03-26 22:46:25 -07:00
|
|
|
let mut r = MemReader::new(vec!(0, 1, 2));
|
2013-12-09 22:53:09 -08:00
|
|
|
{
|
2014-02-13 23:28:11 -05:00
|
|
|
let mut r = LimitReader::new(r.by_ref(), 4);
|
2014-03-26 09:24:16 -07:00
|
|
|
assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
2014-02-15 13:51:37 -08:00
|
|
|
fn test_limit_reader_limited() {
|
2014-03-26 22:46:25 -07:00
|
|
|
let mut r = MemReader::new(vec!(0, 1, 2));
|
2013-12-09 22:53:09 -08:00
|
|
|
{
|
2014-02-13 23:28:11 -05:00
|
|
|
let mut r = LimitReader::new(r.by_ref(), 2);
|
2014-03-26 09:24:16 -07:00
|
|
|
assert_eq!(vec!(0, 1), r.read_to_end().unwrap());
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
2014-03-26 09:24:16 -07:00
|
|
|
assert_eq!(vec!(2), r.read_to_end().unwrap());
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
2014-02-15 13:51:37 -08:00
|
|
|
#[test]
|
|
|
|
|
fn test_limit_reader_limit() {
|
2014-03-26 22:46:25 -07:00
|
|
|
let r = MemReader::new(vec!(0, 1, 2));
|
2014-02-15 13:51:37 -08:00
|
|
|
let mut r = LimitReader::new(r, 3);
|
|
|
|
|
assert_eq!(3, r.limit());
|
|
|
|
|
assert_eq!(0, r.read_byte().unwrap());
|
|
|
|
|
assert_eq!(2, r.limit());
|
2014-03-26 09:24:16 -07:00
|
|
|
assert_eq!(vec!(1, 2), r.read_to_end().unwrap());
|
2014-02-15 13:51:37 -08:00
|
|
|
assert_eq!(0, r.limit());
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-14 23:06:30 -07:00
|
|
|
#[test]
|
|
|
|
|
fn test_limit_reader_overlong_consume() {
|
|
|
|
|
let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]);
|
|
|
|
|
let mut r = LimitReader::new(r.by_ref(), 1);
|
|
|
|
|
r.consume(2);
|
|
|
|
|
assert_eq!(vec![], r.read_to_end().unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-09 22:53:09 -08:00
|
|
|
#[test]
|
|
|
|
|
fn test_null_writer() {
|
|
|
|
|
let mut s = NullWriter;
|
2014-06-06 10:27:49 -07:00
|
|
|
let buf = vec![0, 0, 0];
|
|
|
|
|
s.write(buf.as_slice()).unwrap();
|
2014-01-30 14:10:53 -08:00
|
|
|
s.flush().unwrap();
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_zero_reader() {
|
|
|
|
|
let mut s = ZeroReader;
|
2014-06-06 10:27:49 -07:00
|
|
|
let mut buf = vec![1, 2, 3];
|
|
|
|
|
assert_eq!(s.read(buf.as_mut_slice()), Ok(3));
|
|
|
|
|
assert_eq!(vec![0, 0, 0], buf);
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_null_reader() {
|
|
|
|
|
let mut r = NullReader;
|
2014-06-06 10:27:49 -07:00
|
|
|
let mut buf = vec![0];
|
|
|
|
|
assert!(r.read(buf.as_mut_slice()).is_err());
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_multi_writer() {
|
|
|
|
|
static mut writes: uint = 0;
|
|
|
|
|
static mut flushes: uint = 0;
|
|
|
|
|
|
|
|
|
|
struct TestWriter;
|
|
|
|
|
impl Writer for TestWriter {
|
2014-01-30 14:10:53 -08:00
|
|
|
fn write(&mut self, _buf: &[u8]) -> io::IoResult<()> {
|
2013-12-09 22:53:09 -08:00
|
|
|
unsafe { writes += 1 }
|
2014-01-30 14:10:53 -08:00
|
|
|
Ok(())
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
2014-01-30 14:10:53 -08:00
|
|
|
fn flush(&mut self) -> io::IoResult<()> {
|
2013-12-09 22:53:09 -08:00
|
|
|
unsafe { flushes += 1 }
|
2014-01-30 14:10:53 -08:00
|
|
|
Ok(())
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-05 18:56:44 -07:00
|
|
|
let mut multi = MultiWriter::new(vec!(box TestWriter as Box<Writer>,
|
|
|
|
|
box TestWriter as Box<Writer>));
|
2014-11-17 21:39:01 +13:00
|
|
|
multi.write(&[1, 2, 3]).unwrap();
|
2013-12-09 22:53:09 -08:00
|
|
|
assert_eq!(2, unsafe { writes });
|
|
|
|
|
assert_eq!(0, unsafe { flushes });
|
2014-01-30 14:10:53 -08:00
|
|
|
multi.flush().unwrap();
|
2013-12-09 22:53:09 -08:00
|
|
|
assert_eq!(2, unsafe { writes });
|
|
|
|
|
assert_eq!(2, unsafe { flushes });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_chained_reader() {
|
2014-03-26 22:53:30 -07:00
|
|
|
let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()),
|
|
|
|
|
MemReader::new(vec!(2, 3)));
|
2014-09-14 20:27:36 -07:00
|
|
|
let mut r = ChainedReader::new(rs.into_iter());
|
2014-03-26 09:24:16 -07:00
|
|
|
assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap());
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_tee_reader() {
|
2014-03-26 22:46:25 -07:00
|
|
|
let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
|
2014-11-11 16:01:29 -05:00
|
|
|
Vec::new());
|
2014-03-26 09:24:16 -07:00
|
|
|
assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
|
2013-12-09 22:53:09 -08:00
|
|
|
let (_, w) = r.unwrap();
|
2014-11-11 16:01:29 -05:00
|
|
|
assert_eq!(vec!(0, 1, 2), w);
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_copy() {
|
2014-03-26 22:46:25 -07:00
|
|
|
let mut r = MemReader::new(vec!(0, 1, 2, 3, 4));
|
2014-11-11 16:01:29 -05:00
|
|
|
let mut w = Vec::new();
|
2014-01-30 14:10:53 -08:00
|
|
|
copy(&mut r, &mut w).unwrap();
|
2014-11-11 16:01:29 -05:00
|
|
|
assert_eq!(vec!(0, 1, 2, 3, 4), w);
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|
2014-05-05 23:50:07 -07:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn limit_reader_buffer() {
|
2014-11-30 16:55:53 -08:00
|
|
|
let r = &mut b"0123456789\n0123456789\n";
|
2014-05-05 23:50:07 -07:00
|
|
|
{
|
|
|
|
|
let mut r = LimitReader::new(r.by_ref(), 3);
|
2014-06-21 03:39:03 -07:00
|
|
|
assert_eq!(r.read_line(), Ok("012".to_string()));
|
2014-05-05 23:50:07 -07:00
|
|
|
assert_eq!(r.limit(), 0);
|
|
|
|
|
assert_eq!(r.read_line().err().unwrap().kind, io::EndOfFile);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let mut r = LimitReader::new(r.by_ref(), 9);
|
2014-06-21 03:39:03 -07:00
|
|
|
assert_eq!(r.read_line(), Ok("3456789\n".to_string()));
|
2014-05-05 23:50:07 -07:00
|
|
|
assert_eq!(r.limit(), 1);
|
2014-06-21 03:39:03 -07:00
|
|
|
assert_eq!(r.read_line(), Ok("0".to_string()));
|
2014-05-05 23:50:07 -07:00
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
let mut r = LimitReader::new(r.by_ref(), 100);
|
|
|
|
|
assert_eq!(r.read_char(), Ok('1'));
|
|
|
|
|
assert_eq!(r.limit(), 99);
|
2014-06-21 03:39:03 -07:00
|
|
|
assert_eq!(r.read_line(), Ok("23456789\n".to_string()));
|
2014-05-05 23:50:07 -07:00
|
|
|
}
|
|
|
|
|
}
|
2014-06-02 20:42:41 -07:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_iter_reader() {
|
|
|
|
|
let mut r = IterReader::new(range(0u8, 8));
|
|
|
|
|
let mut buf = [0, 0, 0];
|
2014-11-17 21:39:01 +13:00
|
|
|
let len = r.read(&mut buf).unwrap();
|
2014-06-02 20:42:41 -07:00
|
|
|
assert_eq!(len, 3);
|
|
|
|
|
assert!(buf == [0, 1, 2]);
|
|
|
|
|
|
2014-11-17 21:39:01 +13:00
|
|
|
let len = r.read(&mut buf).unwrap();
|
2014-06-02 20:42:41 -07:00
|
|
|
assert_eq!(len, 3);
|
|
|
|
|
assert!(buf == [3, 4, 5]);
|
|
|
|
|
|
2014-11-17 21:39:01 +13:00
|
|
|
let len = r.read(&mut buf).unwrap();
|
2014-06-02 20:42:41 -07:00
|
|
|
assert_eq!(len, 2);
|
|
|
|
|
assert!(buf == [6, 7, 5]);
|
|
|
|
|
|
2014-11-17 21:39:01 +13:00
|
|
|
assert_eq!(r.read(&mut buf).unwrap_err().kind, io::EndOfFile);
|
2014-06-02 20:42:41 -07:00
|
|
|
}
|
2014-08-14 23:06:30 -07:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn iter_reader_zero_length() {
|
|
|
|
|
let mut r = IterReader::new(range(0u8, 8));
|
|
|
|
|
let mut buf = [];
|
2014-11-17 21:39:01 +13:00
|
|
|
assert_eq!(Ok(0), r.read(&mut buf));
|
2014-08-14 23:06:30 -07:00
|
|
|
}
|
2013-12-09 22:53:09 -08:00
|
|
|
}
|