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.
This commit is contained in:
commit
0c74911f87
|
@ -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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use io::{MemReader, MemWriter, BufReader};
|
use io::{MemReader, MemWriter, BufReader};
|
||||||
|
@ -366,4 +396,23 @@ mod test {
|
||||||
assert_eq!(r.read_line(), Ok("23456789\n".to_str()));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue