提交 7bc092f1 编写于 作者: A Alex Crichton

Introduce an io::Buffer trait

This trait is meant to abstract whether a reader is actually implemented with an
underlying buffer. For all readers which are implemented as such, we can
efficiently implement things like read_char, read_line, read_until, etc. There
are two required methods for managing the internal buffer, and otherwise
read_line and friends can all become default methods.

Closes #10334
上级 825b127d
...@@ -55,8 +55,7 @@ ...@@ -55,8 +55,7 @@
use num; use num;
use vec; use vec;
use str; use super::{Stream, Decorator};
use super::{Reader, Writer, Stream, Decorator};
// libuv recommends 64k buffers to maximize throughput // libuv recommends 64k buffers to maximize throughput
// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA // https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
...@@ -93,45 +92,10 @@ pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> { ...@@ -93,45 +92,10 @@ pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
pub fn new(inner: R) -> BufferedReader<R> { pub fn new(inner: R) -> BufferedReader<R> {
BufferedReader::with_capacity(DEFAULT_CAPACITY, inner) BufferedReader::with_capacity(DEFAULT_CAPACITY, inner)
} }
}
/// Reads the next line of input, interpreted as a sequence of utf-8 impl<R: Reader> Buffer for BufferedReader<R> {
/// encoded unicode codepoints. If a newline is encountered, then the fn fill<'a>(&'a mut self) -> &'a [u8] {
/// newline is contained in the returned string.
pub fn read_line(&mut self) -> Option<~str> {
self.read_until('\n' as u8).map(str::from_utf8_owned)
}
/// Reads a sequence of bytes leading up to a specified delimeter. Once the
/// specified byte is encountered, reading ceases and the bytes up to and
/// including the delimiter are returned.
pub fn read_until(&mut self, byte: u8) -> Option<~[u8]> {
let mut res = ~[];
let mut used;
loop {
{
let available = self.fill_buffer();
match available.iter().position(|&b| b == byte) {
Some(i) => {
res.push_all(available.slice_to(i + 1));
used = i + 1;
break
}
None => {
res.push_all(available);
used = available.len();
}
}
}
if used == 0 {
break
}
self.pos += used;
}
self.pos += used;
return if res.len() == 0 {None} else {Some(res)};
}
fn fill_buffer<'a>(&'a mut self) -> &'a [u8] {
if self.pos == self.cap { if self.pos == self.cap {
match self.inner.read(self.buf) { match self.inner.read(self.buf) {
Some(cap) => { Some(cap) => {
...@@ -143,12 +107,17 @@ fn fill_buffer<'a>(&'a mut self) -> &'a [u8] { ...@@ -143,12 +107,17 @@ fn fill_buffer<'a>(&'a mut self) -> &'a [u8] {
} }
return self.buf.slice(self.pos, self.cap); return self.buf.slice(self.pos, self.cap);
} }
fn consume(&mut self, amt: uint) {
self.pos += amt;
assert!(self.pos <= self.cap);
}
} }
impl<R: Reader> Reader for BufferedReader<R> { impl<R: Reader> Reader for BufferedReader<R> {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
let nread = { let nread = {
let available = self.fill_buffer(); let available = self.fill();
if available.len() == 0 { if available.len() == 0 {
return None; return None;
} }
...@@ -166,17 +135,9 @@ fn eof(&mut self) -> bool { ...@@ -166,17 +135,9 @@ fn eof(&mut self) -> bool {
} }
impl<R: Reader> Decorator<R> for BufferedReader<R> { impl<R: Reader> Decorator<R> for BufferedReader<R> {
fn inner(self) -> R { fn inner(self) -> R { self.inner }
self.inner fn inner_ref<'a>(&'a self) -> &'a R { &self.inner }
} fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { &mut self.inner }
fn inner_ref<'a>(&'a self) -> &'a R {
&self.inner
}
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R {
&mut self.inner
}
} }
/// Wraps a Writer and buffers output to it /// Wraps a Writer and buffers output to it
...@@ -279,13 +240,8 @@ fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { self.inner.inner_mut_ref() } ...@@ -279,13 +240,8 @@ fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { self.inner.inner_mut_ref() }
struct InternalBufferedWriter<W>(BufferedWriter<W>); struct InternalBufferedWriter<W>(BufferedWriter<W>);
impl<W: Reader> Reader for InternalBufferedWriter<W> { impl<W: Reader> Reader for InternalBufferedWriter<W> {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.inner.read(buf) }
self.inner.read(buf) fn eof(&mut self) -> bool { self.inner.eof() }
}
fn eof(&mut self) -> bool {
self.inner.eof()
}
} }
/// Wraps a Stream and buffers input and output to and from it /// Wraps a Stream and buffers input and output to and from it
...@@ -311,35 +267,24 @@ pub fn new(inner: S) -> BufferedStream<S> { ...@@ -311,35 +267,24 @@ pub fn new(inner: S) -> BufferedStream<S> {
} }
} }
impl<S: Stream> Reader for BufferedStream<S> { impl<S: Stream> Buffer for BufferedStream<S> {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { fn fill<'a>(&'a mut self) -> &'a [u8] { self.inner.fill() }
self.inner.read(buf) fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
} }
fn eof(&mut self) -> bool { impl<S: Stream> Reader for BufferedStream<S> {
self.inner.eof() fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.inner.read(buf) }
} fn eof(&mut self) -> bool { self.inner.eof() }
} }
impl<S: Stream> Writer for BufferedStream<S> { impl<S: Stream> Writer for BufferedStream<S> {
fn write(&mut self, buf: &[u8]) { fn write(&mut self, buf: &[u8]) { self.inner.inner.write(buf) }
self.inner.inner.write(buf) fn flush(&mut self) { self.inner.inner.flush() }
}
fn flush(&mut self) {
self.inner.inner.flush()
}
} }
impl<S: Stream> Decorator<S> for BufferedStream<S> { impl<S: Stream> Decorator<S> for BufferedStream<S> {
fn inner(self) -> S { fn inner(self) -> S { self.inner.inner.inner() }
self.inner.inner.inner() fn inner_ref<'a>(&'a self) -> &'a S { self.inner.inner.inner_ref() }
}
fn inner_ref<'a>(&'a self) -> &'a S {
self.inner.inner.inner_ref()
}
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut S { fn inner_mut_ref<'a>(&'a mut self) -> &'a mut S {
self.inner.inner.inner_mut_ref() self.inner.inner.inner_mut_ref()
} }
......
...@@ -119,29 +119,18 @@ fn eof(&mut self) -> bool { self.pos == self.buf.len() } ...@@ -119,29 +119,18 @@ fn eof(&mut self) -> bool { self.pos == self.buf.len() }
impl Seek for MemReader { impl Seek for MemReader {
fn tell(&self) -> u64 { self.pos as u64 } fn tell(&self) -> u64 { self.pos as u64 }
fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
} }
impl Decorator<~[u8]> for MemReader { impl Buffer for MemReader {
fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) }
fn inner(self) -> ~[u8] { fn consume(&mut self, amt: uint) { self.pos += amt; }
match self { }
MemReader { buf: buf, _ } => buf
}
}
fn inner_ref<'a>(&'a self) -> &'a ~[u8] {
match *self {
MemReader { buf: ref buf, _ } => buf
}
}
fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { impl Decorator<~[u8]> for MemReader {
match *self { fn inner(self) -> ~[u8] { self.buf }
MemReader { buf: ref mut buf, _ } => buf fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
} fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
}
} }
...@@ -214,6 +203,11 @@ fn tell(&self) -> u64 { self.pos as u64 } ...@@ -214,6 +203,11 @@ fn tell(&self) -> u64 { self.pos as u64 }
fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
} }
impl<'self> Buffer for BufReader<'self> {
fn fill<'a>(&'a mut self) -> &'a [u8] { self.buf.slice_from(self.pos) }
fn consume(&mut self, amt: uint) { self.pos += amt; }
}
///Calls a function with a MemWriter and returns ///Calls a function with a MemWriter and returns
///the writer's stored vector. ///the writer's stored vector.
pub fn with_mem_writer(writeFn:&fn(&mut MemWriter)) -> ~[u8] { pub fn with_mem_writer(writeFn:&fn(&mut MemWriter)) -> ~[u8] {
......
...@@ -247,11 +247,12 @@ ...@@ -247,11 +247,12 @@
use option::{Option, Some, None}; use option::{Option, Some, None};
use path::Path; use path::Path;
use result::{Ok, Err, Result}; use result::{Ok, Err, Result};
use str;
use str::{StrSlice, OwnedStr}; use str::{StrSlice, OwnedStr};
use to_str::ToStr; use to_str::ToStr;
use uint; use uint;
use unstable::finally::Finally; use unstable::finally::Finally;
use vec::{OwnedVector, MutableVector}; use vec::{OwnedVector, MutableVector, ImmutableVector, OwnedCopyableVector};
use vec; use vec;
// Reexports // Reexports
...@@ -977,6 +978,78 @@ pub trait Stream: Reader + Writer { } ...@@ -977,6 +978,78 @@ pub trait Stream: Reader + Writer { }
impl<T: Reader + Writer> Stream for T {} impl<T: Reader + Writer> Stream for T {}
/// A Buffer is a type of reader which has some form of internal buffering to
/// allow certain kinds of reading operations to be more optimized than others.
/// This type extends the `Reader` trait with a few methods that are not
/// possible to reasonably implement with purely a read interface.
pub trait Buffer: Reader {
/// Fills the internal buffer of this object, returning the buffer contents.
/// Note that none of the contents will be "read" in the sense that later
/// calling `read` may return the same contents.
///
/// The `consume` function must be called with the number of bytes that are
/// consumed from this buffer returned to ensure that the bytes are never
/// returned twice.
///
/// # Failure
///
/// This function will raise on the `io_error` condition if a read error is
/// encountered.
fn fill<'a>(&'a mut self) -> &'a [u8];
/// Tells this buffer that `amt` bytes have been consumed from the buffer,
/// so they should no longer be returned in calls to `fill` or `read`.
fn consume(&mut self, amt: uint);
/// Reads the next line of input, interpreted as a sequence of utf-8
/// encoded unicode codepoints. If a newline is encountered, then the
/// newline is contained in the returned string.
///
/// # Failure
///
/// This function will raise on the `io_error` condition if a read error is
/// encountered. The task will also fail if sequence of bytes leading up to
/// the newline character are not valid utf-8.
fn read_line(&mut self) -> Option<~str> {
self.read_until('\n' as u8).map(str::from_utf8_owned)
}
/// Reads a sequence of bytes leading up to a specified delimeter. Once the
/// specified byte is encountered, reading ceases and the bytes up to and
/// including the delimiter are returned.
///
/// # Failure
///
/// This function will raise on the `io_error` condition if a read error is
/// encountered.
fn read_until(&mut self, byte: u8) -> Option<~[u8]> {
let mut res = ~[];
let mut used;
loop {
{
let available = self.fill();
match available.iter().position(|&b| b == byte) {
Some(i) => {
res.push_all(available.slice_to(i + 1));
used = i + 1;
break
}
None => {
res.push_all(available);
used = available.len();
}
}
}
if used == 0 {
break
}
self.consume(used);
}
self.consume(used);
return if res.len() == 0 {None} else {Some(res)};
}
}
pub enum SeekStyle { pub enum SeekStyle {
/// Seek from the beginning of the stream /// Seek from the beginning of the stream
SeekSet, SeekSet,
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive}; pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
pub use path::{GenericPath, Path, PosixPath, WindowsPath}; pub use path::{GenericPath, Path, PosixPath, WindowsPath};
pub use ptr::RawPtr; pub use ptr::RawPtr;
pub use io::{Writer, Reader, Seek}; pub use io::{Buffer, Writer, Reader, Seek};
pub use send_str::{SendStr, SendStrOwned, SendStrStatic, IntoSendStr}; pub use send_str::{SendStr, SendStrOwned, SendStrStatic, IntoSendStr};
pub use str::{Str, StrVector, StrSlice, OwnedStr}; pub use str::{Str, StrVector, StrSlice, OwnedStr};
pub use to_bytes::IterBytes; pub use to_bytes::IterBytes;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册