1
Fork 0

Add provided methods Seek::{stream_len, stream_position}

These two methods are defined in terms of `Seek::seek` and are
added for convenience. Tests are included.
This commit is contained in:
Lukas Kalbertodt 2019-02-13 12:19:58 +01:00
parent 913ad6d1f0
commit e8ee00a649
No known key found for this signature in database
GPG key ID: 3CBAF4153F818627

View file

@ -1329,6 +1329,78 @@ pub trait Seek {
/// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
#[stable(feature = "rust1", since = "1.0.0")]
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
/// Returns the length of this stream (in bytes).
///
/// This method is implemented using three seek operations. If this method
/// returns successfully, the seek position is unchanged (i.e. the position
/// before calling this method is the same as afterwards). However, if this
/// method returns an error, the seek position is undefined.
///
/// If you need to obtain the length of *many* streams and you don't care
/// about the seek position afterwards, you can reduce the number of seek
/// operations by simply calling `seek(SeekFrom::End(0))` and use its
/// return value (it is also the stream length).
///
/// Note that length of a stream can change over time (for example, when
/// data is appended to a file). So calling this method multiply times does
/// not necessarily return the same length each time.
///
///
/// # Example
///
/// ```no_run
/// #![feature(seek_convenience)]
/// use std::{
/// io::{self, Seek},
/// fs::File,
/// };
///
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
///
/// let len = f.stream_len()?;
/// println!("The file is currently {} bytes long", len);
/// Ok(())
/// }
/// ```
#[unstable(feature = "seek_convenience", issue = "0")]
fn stream_len(&mut self) -> Result<u64> {
let old_pos = self.stream_position()?;
let len = self.seek(SeekFrom::End(0))?;
self.seek(SeekFrom::Start(old_pos))?;
Ok(len)
}
/// Returns the current seek position from the start of the stream.
///
/// This is equivalent to `self.seek(SeekFrom::Current(0))`.
///
///
/// # Example
///
/// ```no_run
/// #![feature(seek_convenience)]
/// use std::{
/// io::{self, BufRead, BufReader, Seek},
/// fs::File,
/// };
///
/// fn main() -> io::Result<()> {
/// let mut f = BufReader::new(File::open("foo.txt")?);
///
/// let before = f.stream_position()?;
/// f.read_line(&mut String::new())?;
/// let after = f.stream_position()?;
///
/// println!("The first line was {} bytes long", after - before);
/// Ok(())
/// }
/// ```
#[unstable(feature = "seek_convenience", issue = "0")]
fn stream_position(&mut self) -> Result<u64> {
self.seek(SeekFrom::Current(0))
}
}
/// Enumeration of possible methods to seek within an I/O object.
@ -2157,8 +2229,7 @@ impl<B: BufRead> Iterator for Lines<B> {
mod tests {
use crate::io::prelude::*;
use crate::io;
use super::Cursor;
use super::repeat;
use super::{Cursor, SeekFrom, repeat};
#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
@ -2380,4 +2451,50 @@ mod tests {
super::read_to_end(&mut lr, &mut vec)
});
}
#[test]
fn seek_len() -> io::Result<()> {
let mut c = Cursor::new(vec![0; 15]);
assert_eq!(c.stream_len()?, 15);
c.seek(SeekFrom::End(0))?;
let old_pos = c.stream_position()?;
assert_eq!(c.stream_len()?, 15);
assert_eq!(c.stream_position()?, old_pos);
c.seek(SeekFrom::Start(7))?;
c.seek(SeekFrom::Current(2))?;
let old_pos = c.stream_position()?;
assert_eq!(c.stream_len()?, 15);
assert_eq!(c.stream_position()?, old_pos);
Ok(())
}
#[test]
fn seek_position() -> io::Result<()> {
// All `asserts` are duplicated here to make sure the method does not
// change anything about the seek state.
let mut c = Cursor::new(vec![0; 15]);
assert_eq!(c.stream_position()?, 0);
assert_eq!(c.stream_position()?, 0);
c.seek(SeekFrom::End(0))?;
assert_eq!(c.stream_position()?, 15);
assert_eq!(c.stream_position()?, 15);
c.seek(SeekFrom::Start(7))?;
c.seek(SeekFrom::Current(2))?;
assert_eq!(c.stream_position()?, 9);
assert_eq!(c.stream_position()?, 9);
c.seek(SeekFrom::End(-3))?;
c.seek(SeekFrom::Current(1))?;
c.seek(SeekFrom::Current(-5))?;
assert_eq!(c.stream_position()?, 8);
assert_eq!(c.stream_position()?, 8);
Ok(())
}
}