about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-07 20:36:37 -0700
committerbors <bors@rust-lang.org>2014-05-07 20:36:37 -0700
commite0fcb4eb3d516017c7c2fa8d17e7b8b82bdc065b (patch)
tree1084f3850e030cbbb92220c78959960ea72cb771 /src/libstd
parentab22d99e73f81f35dd4edbdc9b27152dc653f5b6 (diff)
parent678b1659f9a9536a4ee9901e2cd51c7daa4532c9 (diff)
downloadrust-e0fcb4eb3d516017c7c2fa8d17e7b8b82bdc065b.tar.gz
rust-e0fcb4eb3d516017c7c2fa8d17e7b8b82bdc065b.zip
auto merge of #13964 : alexcrichton/rust/more-buffers, r=brson
This will allow methods like read_line() on RefReader, LimitReader, etc.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/mod.rs5
-rw-r--r--src/libstd/io/util.rs59
2 files changed, 63 insertions, 1 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index cd069ddc1ea..e2fde98a77c 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -853,6 +853,11 @@ impl<'a, R: Reader> Reader for RefReader<'a, R> {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.inner.read(buf) }
 }
 
+impl<'a, R: Buffer> Buffer for RefReader<'a, R> {
+    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() }
+    fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
+}
+
 fn extend_sign(val: u64, nbytes: uint) -> i64 {
     let shift = (8 - nbytes) * 8;
     (val << shift) as i64 >> shift
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index b2e6b27caab..05d5f19eeff 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -55,6 +55,24 @@ impl<R: Reader> Reader for LimitReader<R> {
     }
 }
 
+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());
+        let buf = amt.slice_to(cmp::min(amt.len(), self.limit));
+        if buf.len() == 0 {
+            Err(io::standard_error(io::EndOfFile))
+        } else {
+            Ok(buf)
+        }
+    }
+
+    fn consume(&mut self, amt: uint) {
+        self.limit -= amt;
+        self.inner.consume(amt);
+    }
+
+}
+
 /// A `Writer` which ignores bytes written to it, like /dev/null.
 pub struct NullWriter;
 
@@ -74,6 +92,14 @@ impl Reader for ZeroReader {
     }
 }
 
+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())
+    }
+    fn consume(&mut self, _amt: uint) {}
+}
+
 /// A `Reader` which is always at EOF, like /dev/null.
 pub struct NullReader;
 
@@ -84,6 +110,13 @@ impl Reader for NullReader {
     }
 }
 
+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) {}
+}
+
 /// A `Writer` which multiplexes writes to a set of `Writers`.
 pub struct MultiWriter {
     writers: Vec<Box<Writer>>
@@ -198,8 +231,8 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
 
 #[cfg(test)]
 mod test {
+    use io::{MemReader, MemWriter, BufReader};
     use io;
-    use io::{MemReader, MemWriter};
     use owned::Box;
     use super::*;
     use prelude::*;
@@ -309,4 +342,28 @@ mod test {
         copy(&mut r, &mut w).unwrap();
         assert_eq!(vec!(0, 1, 2, 3, 4), w.unwrap());
     }
+
+    #[test]
+    fn limit_reader_buffer() {
+        let data = "0123456789\n0123456789\n";
+        let mut r = BufReader::new(data.as_bytes());
+        {
+            let mut r = LimitReader::new(r.by_ref(), 3);
+            assert_eq!(r.read_line(), Ok("012".to_str()));
+            assert_eq!(r.limit(), 0);
+            assert_eq!(r.read_line().err().unwrap().kind, io::EndOfFile);
+        }
+        {
+            let mut r = LimitReader::new(r.by_ref(), 9);
+            assert_eq!(r.read_line(), Ok("3456789\n".to_str()));
+            assert_eq!(r.limit(), 1);
+            assert_eq!(r.read_line(), Ok("0".to_str()));
+        }
+        {
+            let mut r = LimitReader::new(r.by_ref(), 100);
+            assert_eq!(r.read_char(), Ok('1'));
+            assert_eq!(r.limit(), 99);
+            assert_eq!(r.read_line(), Ok("23456789\n".to_str()));
+        }
+    }
 }