auto merge of #18980 : erickt/rust/reader, r=erickt

This continues the work @thestinger started in #18885 (which hasn't landed yet, so wait for that to land before landing this one). Instead of adding more methods to `BufReader`, this just allows a `&[u8]` to be used directly as a `Reader`. It also adds an impl of `Writer` for `&mut [u8]`.
This commit is contained in:
bors 2014-12-04 21:33:07 +00:00
commit d9c7c00b9a
6 changed files with 89 additions and 21 deletions

View File

@ -444,15 +444,14 @@ impl<T, E> Result<T, E> {
/// ignoring I/O and parse errors: /// ignoring I/O and parse errors:
/// ///
/// ``` /// ```
/// use std::io::{BufReader, IoResult}; /// use std::io::IoResult;
/// ///
/// let buffer = "1\n2\n3\n4\n"; /// let mut buffer = &mut b"1\n2\n3\n4\n";
/// let mut reader = BufReader::new(buffer.as_bytes());
/// ///
/// let mut sum = 0; /// let mut sum = 0;
/// ///
/// while !reader.eof() { /// while !buffer.is_empty() {
/// let line: IoResult<String> = reader.read_line(); /// let line: IoResult<String> = buffer.read_line();
/// // Convert the string line to a number using `map` and `from_str` /// // Convert the string line to a number using `map` and `from_str`
/// let val: IoResult<int> = line.map(|line| { /// let val: IoResult<int> = line.map(|line| {
/// from_str::<int>(line.as_slice().trim_right()).unwrap_or(0) /// from_str::<int>(line.as_slice().trim_right()).unwrap_or(0)

View File

@ -547,7 +547,7 @@ mod tests {
use self::NodeLabels::*; use self::NodeLabels::*;
use super::{Id, LabelText, LabelStr, EscStr, Labeller}; use super::{Id, LabelText, LabelStr, EscStr, Labeller};
use super::{Nodes, Edges, GraphWalk, render}; use super::{Nodes, Edges, GraphWalk, render};
use std::io::{BufReader, IoResult}; use std::io::IoResult;
use std::str; use std::str;
/// each node is an index in a vector in the graph. /// each node is an index in a vector in the graph.
@ -698,8 +698,7 @@ mod tests {
fn test_input(g: LabelledGraph) -> IoResult<String> { fn test_input(g: LabelledGraph) -> IoResult<String> {
let mut writer = Vec::new(); let mut writer = Vec::new();
render(&g, &mut writer).unwrap(); render(&g, &mut writer).unwrap();
let mut r = BufReader::new(writer[]); (&mut writer.as_slice()).read_to_string()
r.read_to_string()
} }
// All of the tests use raw-strings as the format for the expected outputs, // All of the tests use raw-strings as the format for the expected outputs,
@ -811,8 +810,7 @@ r#"digraph hasse_diagram {
edge(1, 3, ";"), edge(2, 3, ";" ))); edge(1, 3, ";"), edge(2, 3, ";" )));
render(&g, &mut writer).unwrap(); render(&g, &mut writer).unwrap();
let mut r = BufReader::new(writer[]); let r = (&mut writer.as_slice()).read_to_string();
let r = r.read_to_string();
assert_eq!(r.unwrap().as_slice(), assert_eq!(r.unwrap().as_slice(),
r#"digraph syntax_tree { r#"digraph syntax_tree {

View File

@ -406,7 +406,7 @@ mod test {
use prelude::*; use prelude::*;
use super::*; use super::*;
use super::super::{IoResult, EndOfFile}; use super::super::{IoResult, EndOfFile};
use super::super::mem::{MemReader, BufReader}; use super::super::mem::MemReader;
use self::test::Bencher; use self::test::Bencher;
use str::StrPrelude; use str::StrPrelude;
@ -626,14 +626,14 @@ mod test {
#[test] #[test]
fn read_char_buffered() { fn read_char_buffered() {
let buf = [195u8, 159u8]; let buf = [195u8, 159u8];
let mut reader = BufferedReader::with_capacity(1, BufReader::new(&buf)); let mut reader = BufferedReader::with_capacity(1, buf[]);
assert_eq!(reader.read_char(), Ok('ß')); assert_eq!(reader.read_char(), Ok('ß'));
} }
#[test] #[test]
fn test_chars() { fn test_chars() {
let buf = [195u8, 159u8, b'a']; let buf = [195u8, 159u8, b'a'];
let mut reader = BufferedReader::with_capacity(1, BufReader::new(&buf)); let mut reader = BufferedReader::with_capacity(1, buf[]);
let mut it = reader.chars(); let mut it = reader.chars();
assert_eq!(it.next(), Some(Ok('ß'))); assert_eq!(it.next(), Some(Ok('ß')));
assert_eq!(it.next(), Some(Ok('a'))); assert_eq!(it.next(), Some(Ok('a')));

View File

@ -206,6 +206,41 @@ impl Buffer for MemReader {
fn consume(&mut self, amt: uint) { self.pos += amt; } fn consume(&mut self, amt: uint) { self.pos += amt; }
} }
impl<'a> Reader for &'a [u8] {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
if self.is_empty() { return Err(io::standard_error(io::EndOfFile)); }
let write_len = min(buf.len(), self.len());
{
let input = self[..write_len];
let output = buf[mut ..write_len];
slice::bytes::copy_memory(output, input);
}
*self = self.slice_from(write_len);
Ok(write_len)
}
}
impl<'a> Buffer for &'a [u8] {
#[inline]
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
if self.is_empty() {
Err(io::standard_error(io::EndOfFile))
} else {
Ok(*self)
}
}
#[inline]
fn consume(&mut self, amt: uint) {
*self = self[amt..];
}
}
/// Writes to a fixed-size byte slice /// Writes to a fixed-size byte slice
/// ///
/// If a write will not fit in the buffer, it returns an error and does not /// If a write will not fit in the buffer, it returns an error and does not
@ -362,6 +397,16 @@ mod test {
use self::test::Bencher; use self::test::Bencher;
use str::StrPrelude; use str::StrPrelude;
#[test]
fn test_vec_writer() {
let mut writer = Vec::new();
writer.write(&[0]).unwrap();
writer.write(&[1, 2, 3]).unwrap();
writer.write(&[4, 5, 6, 7]).unwrap();
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(writer.as_slice(), b);
}
#[test] #[test]
fn test_mem_writer() { fn test_mem_writer() {
let mut writer = MemWriter::new(); let mut writer = MemWriter::new();
@ -385,6 +430,8 @@ mod test {
assert_eq!(writer.tell(), Ok(8)); assert_eq!(writer.tell(), Ok(8));
writer.write(&[]).unwrap(); writer.write(&[]).unwrap();
assert_eq!(writer.tell(), Ok(8)); assert_eq!(writer.tell(), Ok(8));
assert!(writer.write(&[1]).is_err());
} }
let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(buf.as_slice(), b); assert_eq!(buf.as_slice(), b);
@ -457,6 +504,32 @@ mod test {
assert!(reader.read(&mut buf).is_err()); assert!(reader.read(&mut buf).is_err());
} }
#[test]
fn test_slice_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
let mut reader = &mut in_buf.as_slice();
let mut buf = [];
assert_eq!(reader.read(&mut buf), Ok(0));
let mut buf = [0];
assert_eq!(reader.read(&mut buf), Ok(1));
assert_eq!(reader.len(), 7);
let b: &[_] = &[0];
assert_eq!(buf.as_slice(), b);
let mut buf = [0, ..4];
assert_eq!(reader.read(&mut buf), Ok(4));
assert_eq!(reader.len(), 3);
let b: &[_] = &[1, 2, 3, 4];
assert_eq!(buf.as_slice(), b);
assert_eq!(reader.read(&mut buf), Ok(3));
let b: &[_] = &[5, 6, 7];
assert_eq!(buf[0..3], b);
assert!(reader.read(&mut buf).is_err());
let mut reader = &mut in_buf.as_slice();
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
assert!(reader.read(&mut buf).is_err());
}
#[test] #[test]
fn test_buf_reader() { fn test_buf_reader() {
let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7]; let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];

View File

@ -273,7 +273,7 @@ impl<T: Iterator<u8>> Reader for IterReader<T> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use io::{MemReader, BufReader, ByRefReader}; use io::{MemReader, ByRefReader};
use io; use io;
use boxed::Box; use boxed::Box;
use super::*; use super::*;
@ -395,8 +395,7 @@ mod test {
#[test] #[test]
fn limit_reader_buffer() { fn limit_reader_buffer() {
let data = "0123456789\n0123456789\n"; let r = &mut b"0123456789\n0123456789\n";
let mut r = BufReader::new(data.as_bytes());
{ {
let mut r = LimitReader::new(r.by_ref(), 3); let mut r = LimitReader::new(r.by_ref(), 3);
assert_eq!(r.read_line(), Ok("012".to_string())); assert_eq!(r.read_line(), Ok("012".to_string()));

View File

@ -32,7 +32,6 @@ use self::Fmt::*;
use std::fmt::Show; use std::fmt::Show;
use std::fmt; use std::fmt;
use std::io::BufReader;
use std::num::SignedInt; use std::num::SignedInt;
use std::string::String; use std::string::String;
use std::time::Duration; use std::time::Duration;
@ -1187,7 +1186,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ParseError> {
} }
} }
let mut rdr = BufReader::new(format.as_bytes()); let mut rdr: &[u8] = format.as_bytes();
let mut tm = Tm { let mut tm = Tm {
tm_sec: 0_i32, tm_sec: 0_i32,
tm_min: 0_i32, tm_min: 0_i32,
@ -1211,13 +1210,13 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ParseError> {
let next = range.next; let next = range.next;
let mut buf = [0]; let mut buf = [0];
let c = match rdr.read(&mut buf) { let c = match (&mut rdr).read(&mut buf) {
Ok(..) => buf[0] as char, Ok(..) => buf[0] as char,
Err(..) => break Err(..) => break
}; };
match c { match c {
'%' => { '%' => {
let ch = match rdr.read(&mut buf) { let ch = match (&mut rdr).read(&mut buf) {
Ok(..) => buf[0] as char, Ok(..) => buf[0] as char,
Err(..) => break Err(..) => break
}; };
@ -1233,7 +1232,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ParseError> {
} }
} }
if pos == len && rdr.tell().unwrap() == format.len() as u64 { if pos == len && (&mut rdr).is_empty() {
Ok(Tm { Ok(Tm {
tm_sec: tm.tm_sec, tm_sec: tm.tm_sec,
tm_min: tm.tm_min, tm_min: tm.tm_min,