1
Fork 0

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:
bors 2014-01-09 09:31:36 -08:00
commit 63ba93f91d
16 changed files with 19 additions and 144 deletions

View file

@ -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,

View file

@ -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 {

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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]

View file

@ -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!() }
}

View file

@ -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 {

View 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]

View file

@ -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 {

View file

@ -67,8 +67,6 @@ impl Reader for TcpStream {
}
}
}
fn eof(&mut self) -> bool { fail!() }
}
impl Writer for TcpStream {

View file

@ -86,8 +86,6 @@ impl Reader for UdpStream {
}
})
}
fn eof(&mut self) -> bool { fail!() }
}
impl Writer for UdpStream {

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -66,8 +66,6 @@ impl Reader for PipeStream {
}
}
}
fn eof(&mut self) -> bool { false }
}
impl Writer for PipeStream {

View file

@ -272,8 +272,6 @@ impl Reader for StdReader {
}
}
}
fn eof(&mut self) -> bool { false }
}
/// Representation of a writer to a standard output stream

View file

@ -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());
}
}