Skip to content

Commit 678b165

Browse files
committed
std: Implement the Buffer trait for some wrappers
This will allow methods like read_line() on RefReader, LimitReader, etc.
1 parent ef6daf9 commit 678b165

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

src/libstd/io/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,11 @@ impl<'a, R: Reader> Reader for RefReader<'a, R> {
853853
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.inner.read(buf) }
854854
}
855855

856+
impl<'a, R: Buffer> Buffer for RefReader<'a, R> {
857+
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() }
858+
fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
859+
}
860+
856861
fn extend_sign(val: u64, nbytes: uint) -> i64 {
857862
let shift = (8 - nbytes) * 8;
858863
(val << shift) as i64 >> shift

src/libstd/io/util.rs

+58-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ impl<R: Reader> Reader for LimitReader<R> {
5555
}
5656
}
5757

58+
impl<R: Buffer> Buffer for LimitReader<R> {
59+
fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
60+
let amt = try!(self.inner.fill_buf());
61+
let buf = amt.slice_to(cmp::min(amt.len(), self.limit));
62+
if buf.len() == 0 {
63+
Err(io::standard_error(io::EndOfFile))
64+
} else {
65+
Ok(buf)
66+
}
67+
}
68+
69+
fn consume(&mut self, amt: uint) {
70+
self.limit -= amt;
71+
self.inner.consume(amt);
72+
}
73+
74+
}
75+
5876
/// A `Writer` which ignores bytes written to it, like /dev/null.
5977
pub struct NullWriter;
6078

@@ -74,6 +92,14 @@ impl Reader for ZeroReader {
7492
}
7593
}
7694

95+
impl Buffer for ZeroReader {
96+
fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
97+
static DATA: [u8, ..64] = [0, ..64];
98+
Ok(DATA.as_slice())
99+
}
100+
fn consume(&mut self, _amt: uint) {}
101+
}
102+
77103
/// A `Reader` which is always at EOF, like /dev/null.
78104
pub struct NullReader;
79105

@@ -84,6 +110,13 @@ impl Reader for NullReader {
84110
}
85111
}
86112

113+
impl Buffer for NullReader {
114+
fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
115+
Err(io::standard_error(io::EndOfFile))
116+
}
117+
fn consume(&mut self, _amt: uint) {}
118+
}
119+
87120
/// A `Writer` which multiplexes writes to a set of `Writers`.
88121
pub struct MultiWriter {
89122
writers: Vec<Box<Writer>>
@@ -198,8 +231,8 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
198231

199232
#[cfg(test)]
200233
mod test {
234+
use io::{MemReader, MemWriter, BufReader};
201235
use io;
202-
use io::{MemReader, MemWriter};
203236
use owned::Box;
204237
use super::*;
205238
use prelude::*;
@@ -309,4 +342,28 @@ mod test {
309342
copy(&mut r, &mut w).unwrap();
310343
assert_eq!(vec!(0, 1, 2, 3, 4), w.unwrap());
311344
}
345+
346+
#[test]
347+
fn limit_reader_buffer() {
348+
let data = "0123456789\n0123456789\n";
349+
let mut r = BufReader::new(data.as_bytes());
350+
{
351+
let mut r = LimitReader::new(r.by_ref(), 3);
352+
assert_eq!(r.read_line(), Ok("012".to_str()));
353+
assert_eq!(r.limit(), 0);
354+
assert_eq!(r.read_line().err().unwrap().kind, io::EndOfFile);
355+
}
356+
{
357+
let mut r = LimitReader::new(r.by_ref(), 9);
358+
assert_eq!(r.read_line(), Ok("3456789\n".to_str()));
359+
assert_eq!(r.limit(), 1);
360+
assert_eq!(r.read_line(), Ok("0".to_str()));
361+
}
362+
{
363+
let mut r = LimitReader::new(r.by_ref(), 100);
364+
assert_eq!(r.read_char(), Ok('1'));
365+
assert_eq!(r.limit(), 99);
366+
assert_eq!(r.read_line(), Ok("23456789\n".to_str()));
367+
}
368+
}
312369
}

0 commit comments

Comments
 (0)