auto merge of #11376 : alexcrichton/rust/remove-eof, r=pcwalton
This is something I have been meaning to do for awhile, but upon inspection of the `eof` method on all of the `Reader` impls you may find some interesting surprises. The method returns a good answer for almost all wrapped I/O objects (buffered readers, mem readers, util readers, etc), but the actual return value on all I/O objects themselves is almost always useless. Almost no I/O object other than a file actually knows when it's hit EOF or not. I think that pretending that all objects know when they've hit the end when almost none do is probably a bad idea. I can't really come up with a good answer to "is this file descriptor at eof" or "is this tcp stream at eof" much less "is this udp socket at eof". Due to being unable to answer these questions for *all* readers, I believe that it shouldn't be a part of the core `Reader` trait.
This commit is contained in:
commit
63ba93f91d
16 changed files with 19 additions and 144 deletions
|
@ -788,7 +788,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
|
|||
}
|
||||
}
|
||||
|
||||
if pos == len && rdr.eof() {
|
||||
if pos == len && rdr.tell() as uint == format.len() {
|
||||
Ok(Tm {
|
||||
tm_sec: tm.tm_sec,
|
||||
tm_min: tm.tm_min,
|
||||
|
|
|
@ -114,7 +114,6 @@ impl io::Reader for FileDesc {
|
|||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
|
||||
match self.inner_read(buf) { Ok(n) => Some(n), Err(..) => None }
|
||||
}
|
||||
fn eof(&mut self) -> bool { false }
|
||||
}
|
||||
|
||||
impl io::Writer for FileDesc {
|
||||
|
|
|
@ -66,7 +66,8 @@ pub struct BufferedReader<R> {
|
|||
priv inner: R,
|
||||
priv buf: ~[u8],
|
||||
priv pos: uint,
|
||||
priv cap: uint
|
||||
priv cap: uint,
|
||||
priv eof: bool,
|
||||
}
|
||||
|
||||
impl<R: Reader> BufferedReader<R> {
|
||||
|
@ -84,7 +85,8 @@ impl<R: Reader> BufferedReader<R> {
|
|||
inner: inner,
|
||||
buf: buf,
|
||||
pos: 0,
|
||||
cap: 0
|
||||
cap: 0,
|
||||
eof: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +115,7 @@ impl<R: Reader> Buffer for BufferedReader<R> {
|
|||
self.pos = 0;
|
||||
self.cap = cap;
|
||||
}
|
||||
None => {}
|
||||
None => { self.eof = true; }
|
||||
}
|
||||
}
|
||||
return self.buf.slice(self.pos, self.cap);
|
||||
|
@ -134,15 +136,11 @@ impl<R: Reader> Reader for BufferedReader<R> {
|
|||
nread
|
||||
};
|
||||
self.pos += nread;
|
||||
if nread == 0 && self.inner.eof() && buf.len() != 0 {
|
||||
return None;
|
||||
if nread == 0 && buf.len() != 0 && self.eof {
|
||||
return None;
|
||||
}
|
||||
Some(nread)
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
self.pos == self.cap && self.inner.eof()
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps a Writer and buffers output to it
|
||||
|
@ -270,7 +268,6 @@ impl<W> InternalBufferedWriter<W> {
|
|||
|
||||
impl<W: Reader> Reader for InternalBufferedWriter<W> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.get_mut_ref().inner.read(buf) }
|
||||
fn eof(&mut self) -> bool { self.get_mut_ref().inner.eof() }
|
||||
}
|
||||
|
||||
/// Wraps a Stream and buffers input and output to and from it
|
||||
|
@ -325,7 +322,6 @@ impl<S: Stream> Buffer for BufferedStream<S> {
|
|||
|
||||
impl<S: Stream> Reader for BufferedStream<S> {
|
||||
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> {
|
||||
|
@ -351,10 +347,6 @@ mod test {
|
|||
fn read(&mut self, _: &mut [u8]) -> Option<uint> {
|
||||
None
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl Writer for NullStream {
|
||||
|
@ -370,10 +362,6 @@ mod test {
|
|||
fn read(&mut self, _: &mut [u8]) -> Option<uint> {
|
||||
self.lengths.shift_opt()
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
self.lengths.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -385,24 +373,20 @@ mod test {
|
|||
let nread = reader.read(buf);
|
||||
assert_eq!(Some(2), nread);
|
||||
assert_eq!([0, 1, 0], buf);
|
||||
assert!(!reader.eof());
|
||||
|
||||
let mut buf = [0];
|
||||
let nread = reader.read(buf);
|
||||
assert_eq!(Some(1), nread);
|
||||
assert_eq!([2], buf);
|
||||
assert!(!reader.eof());
|
||||
|
||||
let mut buf = [0, 0, 0];
|
||||
let nread = reader.read(buf);
|
||||
assert_eq!(Some(1), nread);
|
||||
assert_eq!([3, 0, 0], buf);
|
||||
assert!(!reader.eof());
|
||||
|
||||
let nread = reader.read(buf);
|
||||
assert_eq!(Some(1), nread);
|
||||
assert_eq!([4, 0, 0], buf);
|
||||
assert!(reader.eof());
|
||||
|
||||
assert_eq!(None, reader.read(buf));
|
||||
}
|
||||
|
@ -466,13 +450,11 @@ mod test {
|
|||
|
||||
impl io::Reader for S {
|
||||
fn read(&mut self, _: &mut [u8]) -> Option<uint> { None }
|
||||
fn eof(&mut self) -> bool { true }
|
||||
}
|
||||
|
||||
let mut stream = BufferedStream::new(S);
|
||||
let mut buf = [];
|
||||
stream.read(buf);
|
||||
stream.eof();
|
||||
stream.write(buf);
|
||||
stream.flush();
|
||||
}
|
||||
|
@ -539,6 +521,7 @@ mod test {
|
|||
assert_eq!(reader.read(buf), Some(2));
|
||||
assert_eq!(reader.read(buf), Some(0));
|
||||
assert_eq!(reader.read(buf), Some(1));
|
||||
assert_eq!(reader.read(buf), Some(0));
|
||||
assert_eq!(reader.read(buf), None);
|
||||
}
|
||||
|
||||
|
|
|
@ -77,8 +77,6 @@ impl Reader for PortReader {
|
|||
Some(num_read)
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { self.closed }
|
||||
}
|
||||
|
||||
/// Allows writing to a chan.
|
||||
|
@ -133,22 +131,17 @@ mod test {
|
|||
let mut reader = PortReader::new(port);
|
||||
let mut buf = ~[0u8, ..3];
|
||||
|
||||
assert_eq!(false, reader.eof());
|
||||
|
||||
assert_eq!(Some(0), reader.read([]));
|
||||
assert_eq!(false, reader.eof());
|
||||
|
||||
assert_eq!(Some(3), reader.read(buf));
|
||||
assert_eq!(false, reader.eof());
|
||||
assert_eq!(~[1,2,3], buf);
|
||||
|
||||
assert_eq!(Some(3), reader.read(buf));
|
||||
assert_eq!(false, reader.eof());
|
||||
assert_eq!(~[4,5,6], buf);
|
||||
|
||||
assert_eq!(Some(2), reader.read(buf));
|
||||
assert_eq!(~[7,8,6], buf);
|
||||
assert_eq!(true, reader.eof());
|
||||
|
||||
let mut err = None;
|
||||
let result = io::io_error::cond.trap(|io::standard_error(k, _, _)| {
|
||||
|
@ -158,7 +151,6 @@ mod test {
|
|||
});
|
||||
assert_eq!(Some(io::EndOfFile), err);
|
||||
assert_eq!(None, result);
|
||||
assert_eq!(true, reader.eof());
|
||||
assert_eq!(~[7,8,6], buf);
|
||||
|
||||
// Ensure it continues to fail in the same way.
|
||||
|
@ -170,7 +162,6 @@ mod test {
|
|||
});
|
||||
assert_eq!(Some(io::EndOfFile), err);
|
||||
assert_eq!(None, result);
|
||||
assert_eq!(true, reader.eof());
|
||||
assert_eq!(~[7,8,6], buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -150,9 +150,6 @@ mod test {
|
|||
Some(1)
|
||||
}
|
||||
}
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct EofReader;
|
||||
|
@ -161,9 +158,6 @@ mod test {
|
|||
fn read(&mut self, _: &mut [u8]) -> Option<uint> {
|
||||
None
|
||||
}
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct ErroringReader;
|
||||
|
@ -173,9 +167,6 @@ mod test {
|
|||
io_error::cond.raise(placeholder_error());
|
||||
None
|
||||
}
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct PartialReader {
|
||||
|
@ -195,9 +186,6 @@ mod test {
|
|||
Some(2)
|
||||
}
|
||||
}
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct ErroringLaterReader {
|
||||
|
@ -215,9 +203,6 @@ mod test {
|
|||
None
|
||||
}
|
||||
}
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct ThreeChunkReader {
|
||||
|
@ -240,9 +225,6 @@ mod test {
|
|||
None
|
||||
}
|
||||
}
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -49,6 +49,4 @@ impl<R: Reader> InflateReader<R> {
|
|||
|
||||
impl<R: Reader> Reader for InflateReader<R> {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
|
||||
|
||||
fn eof(&mut self) -> bool { fail!() }
|
||||
}
|
||||
|
|
|
@ -205,6 +205,14 @@ impl File {
|
|||
pub fn truncate(&mut self, size: i64) {
|
||||
self.fd.truncate(size).map_err(|e| io_error::cond.raise(e));
|
||||
}
|
||||
|
||||
/// Tests whether this stream has reached EOF.
|
||||
///
|
||||
/// If true, then this file will no longer continue to return data via
|
||||
/// `read`.
|
||||
pub fn eof(&self) -> bool {
|
||||
self.last_nread == 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Unlink a file from the underlying filesystem.
|
||||
|
@ -597,8 +605,6 @@ impl Reader for File {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { self.last_nread == 0 }
|
||||
}
|
||||
|
||||
impl Writer for File {
|
||||
|
|
|
@ -124,7 +124,7 @@ impl MemReader {
|
|||
|
||||
impl Reader for MemReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
|
||||
{ if self.eof() { return None; } }
|
||||
if self.pos == self.buf.len() { return None }
|
||||
|
||||
let write_len = min(buf.len(), self.buf.len() - self.pos);
|
||||
{
|
||||
|
@ -138,8 +138,6 @@ impl Reader for MemReader {
|
|||
|
||||
return Some(write_len);
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { self.pos == self.buf.len() }
|
||||
}
|
||||
|
||||
impl Seek for MemReader {
|
||||
|
@ -222,7 +220,7 @@ impl<'a> BufReader<'a> {
|
|||
|
||||
impl<'a> Reader for BufReader<'a> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
|
||||
{ if self.eof() { return None; } }
|
||||
if self.pos == self.buf.len() { return None }
|
||||
|
||||
let write_len = min(buf.len(), self.buf.len() - self.pos);
|
||||
{
|
||||
|
@ -236,8 +234,6 @@ impl<'a> Reader for BufReader<'a> {
|
|||
|
||||
return Some(write_len);
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { self.pos == self.buf.len() }
|
||||
}
|
||||
|
||||
impl<'a> Seek for BufReader<'a> {
|
||||
|
@ -369,9 +365,7 @@ mod test {
|
|||
assert_eq!(buf, [1, 2, 3, 4]);
|
||||
assert_eq!(reader.read(buf), Some(3));
|
||||
assert_eq!(buf.slice(0, 3), [5, 6, 7]);
|
||||
assert!(reader.eof());
|
||||
assert_eq!(reader.read(buf), None);
|
||||
assert!(reader.eof());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -391,9 +385,7 @@ mod test {
|
|||
assert_eq!(buf, [1, 2, 3, 4]);
|
||||
assert_eq!(reader.read(buf), Some(3));
|
||||
assert_eq!(buf.slice(0, 3), [5, 6, 7]);
|
||||
assert!(reader.eof());
|
||||
assert_eq!(reader.read(buf), None);
|
||||
assert!(reader.eof());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -502,26 +502,6 @@ pub trait Reader {
|
|||
/// Is it actually possible for 0 bytes to be read successfully?
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint>;
|
||||
|
||||
/// Return whether the Reader has reached the end of the stream.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::io;
|
||||
/// # let _g = ::std::io::ignore_io_error();
|
||||
/// let mut reader = io::stdin();
|
||||
///
|
||||
/// let mut bytes = [0, .. 10];
|
||||
/// reader.read(bytes);
|
||||
///
|
||||
/// if reader.eof() { println("stdin() had at most 10 bytes of data."); }
|
||||
/// ```
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Returns `true` on failure.
|
||||
fn eof(&mut self) -> bool;
|
||||
|
||||
// Convenient helper methods based on the above methods
|
||||
|
||||
/// Reads a single byte. Returns `None` on EOF.
|
||||
|
@ -864,12 +844,10 @@ pub trait Reader {
|
|||
|
||||
impl Reader for ~Reader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) }
|
||||
fn eof(&mut self) -> bool { self.eof() }
|
||||
}
|
||||
|
||||
impl<'a> Reader for &'a mut Reader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) }
|
||||
fn eof(&mut self) -> bool { self.eof() }
|
||||
}
|
||||
|
||||
fn extend_sign(val: u64, nbytes: uint) -> i64 {
|
||||
|
|
|
@ -67,8 +67,6 @@ impl Reader for TcpStream {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { fail!() }
|
||||
}
|
||||
|
||||
impl Writer for TcpStream {
|
||||
|
|
|
@ -86,8 +86,6 @@ impl Reader for UdpStream {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { fail!() }
|
||||
}
|
||||
|
||||
impl Writer for UdpStream {
|
||||
|
|
|
@ -67,7 +67,6 @@ impl UnixStream {
|
|||
|
||||
impl Reader for UnixStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.obj.read(buf) }
|
||||
fn eof(&mut self) -> bool { self.obj.eof() }
|
||||
}
|
||||
|
||||
impl Writer for UnixStream {
|
||||
|
|
|
@ -48,16 +48,6 @@ impl<R: Reader> Reader for Option<R> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
match *self {
|
||||
Some(ref mut reader) => reader.eof(),
|
||||
None => {
|
||||
io_error::cond.raise(prev_io_error());
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Seek> Seek for Option<S> {
|
||||
|
@ -145,7 +135,6 @@ mod test {
|
|||
let mut buf = [0, 0];
|
||||
reader.read(buf);
|
||||
assert_eq!(buf, [0, 1]);
|
||||
assert!(!reader.eof());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -161,14 +150,5 @@ mod test {
|
|||
reader.read(buf);
|
||||
});
|
||||
assert!(called);
|
||||
|
||||
let mut called = false;
|
||||
io_error::cond.trap(|err| {
|
||||
assert_eq!(err.kind, PreviousIoError);
|
||||
called = true;
|
||||
}).inside(|| {
|
||||
assert!(reader.eof());
|
||||
});
|
||||
assert!(called);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,8 +66,6 @@ impl Reader for PipeStream {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { false }
|
||||
}
|
||||
|
||||
impl Writer for PipeStream {
|
||||
|
|
|
@ -272,8 +272,6 @@ impl Reader for StdReader {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool { false }
|
||||
}
|
||||
|
||||
/// Representation of a writer to a standard output stream
|
||||
|
|
|
@ -36,10 +36,6 @@ impl<'a, R: Reader> Reader for LimitReader<'a, R> {
|
|||
len
|
||||
})
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
self.limit == 0 || self.inner.eof()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Writer` which ignores bytes written to it, like /dev/null.
|
||||
|
@ -59,11 +55,6 @@ impl Reader for ZeroReader {
|
|||
buf.set_memory(0);
|
||||
Some(buf.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn eof(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Reader` which is always at EOF, like /dev/null.
|
||||
|
@ -74,11 +65,6 @@ impl Reader for NullReader {
|
|||
fn read(&mut self, _buf: &mut [u8]) -> Option<uint> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn eof(&mut self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Writer` which multiplexes writes to a set of `Writers`.
|
||||
|
@ -140,10 +126,6 @@ impl<R: Reader, I: Iterator<R>> Reader for ChainedReader<I, R> {
|
|||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
self.cur_reader.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Reader` which forwards input from another `Reader`, passing it along to
|
||||
|
@ -174,10 +156,6 @@ impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
|
|||
len
|
||||
})
|
||||
}
|
||||
|
||||
fn eof(&mut self) -> bool {
|
||||
self.reader.eof()
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies all data from a `Reader` to a `Writer`.
|
||||
|
@ -204,7 +182,6 @@ mod test {
|
|||
let mut r = LimitReader::new(&mut r, 4);
|
||||
assert_eq!(~[0, 1, 2], r.read_to_end());
|
||||
}
|
||||
assert!(r.eof());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -238,7 +215,6 @@ mod test {
|
|||
let mut r = NullReader;
|
||||
let mut buf = ~[0];
|
||||
assert_eq!(r.read(buf), None);
|
||||
assert!(r.eof());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -289,7 +265,6 @@ mod test {
|
|||
let mut r = MemReader::new(~[0, 1, 2, 3, 4]);
|
||||
let mut w = MemWriter::new();
|
||||
copy(&mut r, &mut w);
|
||||
assert!(r.eof());
|
||||
assert_eq!(~[0, 1, 2, 3, 4], w.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue