diff options
| author | bors <bors@rust-lang.org> | 2014-06-05 00:51:48 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-06-05 00:51:48 -0700 |
| commit | 0c74911f87c12f0680e21e49a8f9c0c85affac78 (patch) | |
| tree | 4589ae45e62f8e981e35c500f1c842225343b3e0 /src/libstd | |
| parent | 073c8f10fc40b07596fd1018a2002db8e6d5222a (diff) | |
| parent | 30a8bcbe3df484f7fa9f2523f429490c97af0382 (diff) | |
| download | rust-0c74911f87c12f0680e21e49a8f9c0c85affac78.tar.gz rust-0c74911f87c12f0680e21e49a8f9c0c85affac78.zip | |
auto merge of #14568 : erickt/rust/slice-update, r=alexcrichton
This PR adds two features to make it possible to transform an `Iterator<u8>` into a `Reader`. The first patch adds a method to mutable slices that allows it to be updated with an `Iterator<T>` without paying for the bounds cost. The second adds a Iterator adaptor, `IterReader`, to provide that `Reader` interface. I had two questions. First, are these named the right things? Second, should `IterReader` instead wrap an `Iterator<Result<u8, E>>`? This would allow you to `IterReader::new(rdr.bytes())`, which could be useful if you want to apply some iterator transformations on a reader while still exporting the Reader interface, but I'd expect there'd be a lot of overhead annotating each byte with an error result.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/util.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 05d5f19eeff..59c42f111d0 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -229,6 +229,36 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> { } } +/// A `Reader` which converts an `Iterator<u8>` into a `Reader`. +pub struct IterReader<T> { + iter: T, +} + +impl<T: Iterator<u8>> IterReader<T> { + /// Create a new `IterReader` which will read from the specified `Iterator`. + pub fn new(iter: T) -> IterReader<T> { + IterReader { + iter: iter, + } + } +} + +impl<T: Iterator<u8>> Reader for IterReader<T> { + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> { + let mut len = 0; + for (slot, elt) in buf.mut_iter().zip(self.iter.by_ref()) { + *slot = elt; + len += 1; + } + if len == 0 { + Err(io::standard_error(io::EndOfFile)) + } else { + Ok(len) + } + } +} + #[cfg(test)] mod test { use io::{MemReader, MemWriter, BufReader}; @@ -366,4 +396,23 @@ mod test { assert_eq!(r.read_line(), Ok("23456789\n".to_str())); } } + + #[test] + fn test_iter_reader() { + let mut r = IterReader::new(range(0u8, 8)); + let mut buf = [0, 0, 0]; + let len = r.read(buf).unwrap(); + assert_eq!(len, 3); + assert!(buf == [0, 1, 2]); + + let len = r.read(buf).unwrap(); + assert_eq!(len, 3); + assert!(buf == [3, 4, 5]); + + let len = r.read(buf).unwrap(); + assert_eq!(len, 2); + assert!(buf == [6, 7, 5]); + + assert_eq!(r.read(buf).unwrap_err().kind, io::EndOfFile); + } } |
