@@ -1329,6 +1329,78 @@ pub trait Seek {
13291329 /// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
13301330 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
13311331 fn seek ( & mut self , pos : SeekFrom ) -> Result < u64 > ;
1332+
1333+ /// Returns the length of this stream (in bytes).
1334+ ///
1335+ /// This method is implemented using three seek operations. If this method
1336+ /// returns successfully, the seek position is unchanged (i.e. the position
1337+ /// before calling this method is the same as afterwards). However, if this
1338+ /// method returns an error, the seek position is undefined.
1339+ ///
1340+ /// If you need to obtain the length of *many* streams and you don't care
1341+ /// about the seek position afterwards, you can reduce the number of seek
1342+ /// operations by simply calling `seek(SeekFrom::End(0))` and use its
1343+ /// return value (it is also the stream length).
1344+ ///
1345+ /// Note that length of a stream can change over time (for example, when
1346+ /// data is appended to a file). So calling this method multiply times does
1347+ /// not necessarily return the same length each time.
1348+ ///
1349+ ///
1350+ /// # Example
1351+ ///
1352+ /// ```no_run
1353+ /// #![feature(seek_convenience)]
1354+ /// use std::{
1355+ /// io::{self, Seek},
1356+ /// fs::File,
1357+ /// };
1358+ ///
1359+ /// fn main() -> io::Result<()> {
1360+ /// let mut f = File::open("foo.txt")?;
1361+ ///
1362+ /// let len = f.stream_len()?;
1363+ /// println!("The file is currently {} bytes long", len);
1364+ /// Ok(())
1365+ /// }
1366+ /// ```
1367+ #[ unstable( feature = "seek_convenience" , issue = "0" ) ]
1368+ fn stream_len ( & mut self ) -> Result < u64 > {
1369+ let old_pos = self . stream_position ( ) ?;
1370+ let len = self . seek ( SeekFrom :: End ( 0 ) ) ?;
1371+ self . seek ( SeekFrom :: Start ( old_pos) ) ?;
1372+ Ok ( len)
1373+ }
1374+
1375+ /// Returns the current seek position from the start of the stream.
1376+ ///
1377+ /// This is equivalent to `self.seek(SeekFrom::Current(0))`.
1378+ ///
1379+ ///
1380+ /// # Example
1381+ ///
1382+ /// ```no_run
1383+ /// #![feature(seek_convenience)]
1384+ /// use std::{
1385+ /// io::{self, BufRead, BufReader, Seek},
1386+ /// fs::File,
1387+ /// };
1388+ ///
1389+ /// fn main() -> io::Result<()> {
1390+ /// let mut f = BufReader::new(File::open("foo.txt")?);
1391+ ///
1392+ /// let before = f.stream_position()?;
1393+ /// f.read_line(&mut String::new())?;
1394+ /// let after = f.stream_position()?;
1395+ ///
1396+ /// println!("The first line was {} bytes long", after - before);
1397+ /// Ok(())
1398+ /// }
1399+ /// ```
1400+ #[ unstable( feature = "seek_convenience" , issue = "0" ) ]
1401+ fn stream_position ( & mut self ) -> Result < u64 > {
1402+ self . seek ( SeekFrom :: Current ( 0 ) )
1403+ }
13321404}
13331405
13341406/// Enumeration of possible methods to seek within an I/O object.
@@ -2157,8 +2229,7 @@ impl<B: BufRead> Iterator for Lines<B> {
21572229mod tests {
21582230 use crate :: io:: prelude:: * ;
21592231 use crate :: io;
2160- use super :: Cursor ;
2161- use super :: repeat;
2232+ use super :: { Cursor , SeekFrom , repeat} ;
21622233
21632234 #[ test]
21642235 #[ cfg_attr( target_os = "emscripten" , ignore) ]
@@ -2380,4 +2451,50 @@ mod tests {
23802451 super :: read_to_end ( & mut lr, & mut vec)
23812452 } ) ;
23822453 }
2454+
2455+ #[ test]
2456+ fn seek_len ( ) -> io:: Result < ( ) > {
2457+ let mut c = Cursor :: new ( vec ! [ 0 ; 15 ] ) ;
2458+ assert_eq ! ( c. stream_len( ) ?, 15 ) ;
2459+
2460+ c. seek ( SeekFrom :: End ( 0 ) ) ?;
2461+ let old_pos = c. stream_position ( ) ?;
2462+ assert_eq ! ( c. stream_len( ) ?, 15 ) ;
2463+ assert_eq ! ( c. stream_position( ) ?, old_pos) ;
2464+
2465+ c. seek ( SeekFrom :: Start ( 7 ) ) ?;
2466+ c. seek ( SeekFrom :: Current ( 2 ) ) ?;
2467+ let old_pos = c. stream_position ( ) ?;
2468+ assert_eq ! ( c. stream_len( ) ?, 15 ) ;
2469+ assert_eq ! ( c. stream_position( ) ?, old_pos) ;
2470+
2471+ Ok ( ( ) )
2472+ }
2473+
2474+ #[ test]
2475+ fn seek_position ( ) -> io:: Result < ( ) > {
2476+ // All `asserts` are duplicated here to make sure the method does not
2477+ // change anything about the seek state.
2478+ let mut c = Cursor :: new ( vec ! [ 0 ; 15 ] ) ;
2479+ assert_eq ! ( c. stream_position( ) ?, 0 ) ;
2480+ assert_eq ! ( c. stream_position( ) ?, 0 ) ;
2481+
2482+ c. seek ( SeekFrom :: End ( 0 ) ) ?;
2483+ assert_eq ! ( c. stream_position( ) ?, 15 ) ;
2484+ assert_eq ! ( c. stream_position( ) ?, 15 ) ;
2485+
2486+
2487+ c. seek ( SeekFrom :: Start ( 7 ) ) ?;
2488+ c. seek ( SeekFrom :: Current ( 2 ) ) ?;
2489+ assert_eq ! ( c. stream_position( ) ?, 9 ) ;
2490+ assert_eq ! ( c. stream_position( ) ?, 9 ) ;
2491+
2492+ c. seek ( SeekFrom :: End ( -3 ) ) ?;
2493+ c. seek ( SeekFrom :: Current ( 1 ) ) ?;
2494+ c. seek ( SeekFrom :: Current ( -5 ) ) ?;
2495+ assert_eq ! ( c. stream_position( ) ?, 8 ) ;
2496+ assert_eq ! ( c. stream_position( ) ?, 8 ) ;
2497+
2498+ Ok ( ( ) )
2499+ }
23832500}
0 commit comments