diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 8ab0d3a550401..b3c73d395a458 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -113,6 +113,17 @@ impl Reader for BufferedReader { self.pos += nread; Ok(nread) } + + fn skip(&mut self, num_bytes: uint) -> IoResult { + let bytes_in_buf = self.cap - self.pos; + Ok( if num_bytes <= bytes_in_buf { + self.pos += num_bytes; + num_bytes + } else { + self.pos += bytes_in_buf; + bytes_in_buf + try!( self.inner.skip(num_bytes - bytes_in_buf) ) + } ) + } } /// Wraps a Writer and buffers output to it diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 8632fc63e52f8..b5b8860422ce3 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -259,6 +259,12 @@ impl File { err.update_err("couldn't fstat file", |e| format!("{}; path={}", e, self.path.display())) } + + /// Call Seek::skip(), not Reader::skip(). + #[inline] + pub fn skip(&mut self, num_bytes: uint) -> IoResult { + Seek::skip(self, num_bytes) + } } /// Unlink a file from the underlying filesystem. diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index f86ae05d623ca..0ecbea269e773 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -137,6 +137,12 @@ impl MemReader { /// Unwraps this `MemReader`, returning the underlying buffer #[inline] pub fn unwrap(self) -> Vec { self.buf } + + /// Call Seek::skip(), not Reader::skip(). + #[inline] + pub fn skip(&mut self, num_bytes: uint) -> IoResult { + Seek::skip(self, num_bytes) + } } impl Reader for MemReader { diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 6e07ff80e2025..d37cf46107aa9 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -243,6 +243,7 @@ use string::String; use uint; use unicode::char::UnicodeChar; use vec::Vec; +use num::ToPrimitive; // Reexports pub use self::stdio::stdin; @@ -1602,6 +1603,16 @@ pub trait Seek { /// stream, but the next write may cause the previous data to be filled in /// with a bit pattern. fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()>; + + /// Wrap seek(num_byes, SeekCur) to provide something similar with Reader::skip(). + /// + /// # Failure + /// + /// Fails when num_bytes doesn't fit into i64. + #[inline] + fn skip(&mut self, num_bytes: uint) -> IoResult { + self.seek(num_bytes.to_i64().unwrap(), SeekCur).and(Ok(num_bytes)) + } } /// A listener is a value that can consume itself to start listening for @@ -1947,6 +1958,10 @@ mod tests { fn new(r: T, behavior: Vec) -> BadReader { BadReader { behavior: behavior, r: r } } + + fn simply_new(r: T) -> BadReader { + BadReader::new(r, vec![]) + } } impl Reader for BadReader { @@ -1976,20 +1991,18 @@ mod tests { #[test] fn test_read_at_least() { - let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), - vec![GoodBehavior(uint::MAX)]); + let mut r = BadReader::simply_new(MemReader::new(b"hello, world!".to_vec())); let mut buf = [0u8, ..5]; assert!(r.read_at_least(1, buf).unwrap() >= 1); assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least assert!(r.read_at_least(0, buf).is_ok()); let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), - vec![BadBehavior(50), GoodBehavior(uint::MAX)]); + vec![BadBehavior(50)]); assert!(r.read_at_least(1, buf).unwrap() >= 1); let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), - vec![BadBehavior(1), GoodBehavior(1), - BadBehavior(50), GoodBehavior(uint::MAX)]); + vec![BadBehavior(1), GoodBehavior(1), BadBehavior(50)]); assert!(r.read_at_least(1, buf).unwrap() >= 1); assert!(r.read_at_least(1, buf).unwrap() >= 1); @@ -2004,19 +2017,17 @@ mod tests { #[test] fn test_push_at_least() { - let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), - vec![GoodBehavior(uint::MAX)]); + let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), vec![]); let mut buf = Vec::new(); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); assert!(r.push_at_least(0, 5, &mut buf).is_ok()); let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), - vec![BadBehavior(50), GoodBehavior(uint::MAX)]); + vec![BadBehavior(50)]); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), - vec![BadBehavior(1), GoodBehavior(1), - BadBehavior(50), GoodBehavior(uint::MAX)]); + vec![BadBehavior(1), GoodBehavior(1), BadBehavior(50)]); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1); @@ -2031,7 +2042,7 @@ mod tests { #[test] fn test_reader_skip() { { - let mut r = MemReader::new(b"hello, world!".to_vec()); + let mut r = BadReader::simply_new(MemReader::new(b"hello, world!".to_vec())); assert_eq!(7, r.skip(7).unwrap()); let mut buf = [0_u8, .. 10]; assert_eq!(6, r.read(buf).unwrap()); @@ -2039,7 +2050,8 @@ mod tests { assert_eq!(EndOfFile, r.skip(0).unwrap_err().kind); } { - let mut r = MemReader::new(Vec::from_fn(SKIP_SIZE + 20, |i| i as u8)); + let mut r = BadReader::simply_new(MemReader::new( + Vec::from_fn(SKIP_SIZE + 20, |i| i as u8))); assert_eq!(10, r.skip(10).unwrap()); assert_eq!(10, r.read_u8().unwrap()); assert_eq!(SKIP_SIZE, r.skip(SKIP_SIZE).unwrap()); @@ -2049,7 +2061,8 @@ mod tests { assert_eq!(EndOfFile, r.read(buf).unwrap_err().kind); } { - let mut r = MemReader::new(Vec::from_fn(SKIP_SIZE + 20, |i| i as u8)); + let mut r = BadReader::simply_new(MemReader::new( + Vec::from_fn(SKIP_SIZE + 20, |i| i as u8))); assert_eq!(SKIP_SIZE, r.skip(SKIP_SIZE).unwrap()); assert_eq!(SKIP_SIZE as u8, r.read_u8().unwrap()); assert_eq!(10, r.skip(10).unwrap()); @@ -2059,7 +2072,8 @@ mod tests { assert_eq!(EndOfFile, r.read(buf).unwrap_err().kind); } { - let mut r = MemReader::new(Vec::from_fn(2 * SKIP_SIZE + 20, |i| i as u8)); + let mut r = BadReader::simply_new(MemReader::new( + Vec::from_fn(2 * SKIP_SIZE + 20, |i| i as u8))); assert_eq!(10, r.skip(10).unwrap()); assert_eq!(10, r.read_u8().unwrap()); assert_eq!(2 * SKIP_SIZE, r.skip(2 * SKIP_SIZE).unwrap());