about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-03-29 01:21:30 -0700
committerbors <bors@rust-lang.org>2016-03-29 01:21:30 -0700
commit161c541afdd18423940e97c7a02b517b1f6d61be (patch)
tree68f37fb340b54580c1f40ed0d9e328985b07c4ef /src/libstd
parent21a4d8098fe3e16ba59f7d3cd435551242e5ec6e (diff)
parentf611e446624d288da7def4ad175405579c8bc310 (diff)
downloadrust-161c541afdd18423940e97c7a02b517b1f6d61be.tar.gz
rust-161c541afdd18423940e97c7a02b517b1f6d61be.zip
Auto merge of #32541 - troplin:chain-bufread, r=alexcrichton
Implement BufRead for Chain

Addresses #32536
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/mod.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 5362f7086bd..0f988c7623e 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1442,6 +1442,27 @@ impl<T: Read, U: Read> Read for Chain<T, U> {
     }
 }
 
+#[stable(feature = "chain_bufread", since = "1.9.0")]
+impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
+    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.
@@ -1844,6 +1865,39 @@ mod tests {
         assert_eq!(0, R.take(0).read(&mut buf).unwrap());
     }
 
+    fn cmp_bufread<Br1: BufRead, Br2: 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(|| {