@@ -348,6 +348,30 @@ impl File {
348348 inner : self . inner . duplicate ( ) ?
349349 } )
350350 }
351+
352+ /// Reads a number of bytes starting from a given offset.
353+ ///
354+ /// The offset is relative to the file start and thus independent from the
355+ /// current cursor.
356+ ///
357+ /// Note that similar to `File::read`, it is not an error to return a short
358+ /// read.
359+ #[ unstable( feature = "file_offset" , issue = "35918" ) ]
360+ pub fn read_at ( & self , buf : & mut [ u8 ] , offset : u64 ) -> io:: Result < usize > {
361+ self . inner . read_at ( buf, offset)
362+ }
363+
364+ /// Writes a number of bytes starting from a given offset.
365+ ///
366+ /// The offset is relative to the file start and thus independent from the
367+ /// current cursor.
368+ ///
369+ /// Note that similar to `File::write`, it is not an error to return a
370+ /// short write.
371+ #[ unstable( feature = "file_offset" , issue = "35918" ) ]
372+ pub fn write_at ( & self , buf : & [ u8 ] , offset : u64 ) -> io:: Result < usize > {
373+ self . inner . write_at ( buf, offset)
374+ }
351375}
352376
353377impl AsInner < fs_imp:: File > for File {
@@ -1893,6 +1917,53 @@ mod tests {
18931917 check ! ( fs:: remove_file( filename) ) ;
18941918 }
18951919
1920+ #[ test]
1921+ fn file_test_io_read_write_at ( ) {
1922+ let tmpdir = tmpdir ( ) ;
1923+ let filename = tmpdir. join ( "file_rt_io_file_test_read_write_at.txt" ) ;
1924+ let mut buf = [ 0 ; 256 ] ;
1925+ let write1 = "asdf" ;
1926+ let write2 = "qwer-" ;
1927+ let write3 = "-zxcv" ;
1928+ let content = "qwer-asdf-zxcv" ;
1929+ {
1930+ let oo = OpenOptions :: new ( ) . create_new ( true ) . write ( true ) . read ( true ) . clone ( ) ;
1931+ let mut rw = check ! ( oo. open( & filename) ) ;
1932+ assert_eq ! ( check!( rw. write_at( write1. as_bytes( ) , 5 ) ) , write1. len( ) ) ;
1933+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 0 ) ;
1934+ assert_eq ! ( check!( rw. read_at( & mut buf, 5 ) ) , write1. len( ) ) ;
1935+ assert_eq ! ( str :: from_utf8( & buf[ ..write1. len( ) ] ) , Ok ( write1) ) ;
1936+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 0 ) ;
1937+ assert_eq ! ( check!( rw. write( write2. as_bytes( ) ) ) , write2. len( ) ) ;
1938+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 5 ) ;
1939+ assert_eq ! ( check!( rw. read( & mut buf) ) , write1. len( ) ) ;
1940+ assert_eq ! ( str :: from_utf8( & buf[ ..write1. len( ) ] ) , Ok ( write1) ) ;
1941+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1942+ assert_eq ! ( check!( rw. read_at( & mut buf[ ..write2. len( ) ] , 0 ) ) , write2. len( ) ) ;
1943+ assert_eq ! ( str :: from_utf8( & buf[ ..write2. len( ) ] ) , Ok ( write2) ) ;
1944+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1945+ assert_eq ! ( check!( rw. write_at( write3. as_bytes( ) , 9 ) ) , write3. len( ) ) ;
1946+ assert_eq ! ( check!( rw. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1947+ }
1948+ {
1949+ let mut read = check ! ( File :: open( & filename) ) ;
1950+ assert_eq ! ( check!( read. read_at( & mut buf, 0 ) ) , content. len( ) ) ;
1951+ assert_eq ! ( str :: from_utf8( & buf[ ..content. len( ) ] ) , Ok ( content) ) ;
1952+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 0 ) ;
1953+ assert_eq ! ( check!( read. seek( SeekFrom :: End ( -5 ) ) ) , 9 ) ;
1954+ assert_eq ! ( check!( read. read_at( & mut buf, 0 ) ) , content. len( ) ) ;
1955+ assert_eq ! ( str :: from_utf8( & buf[ ..content. len( ) ] ) , Ok ( content) ) ;
1956+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 9 ) ;
1957+ assert_eq ! ( check!( read. read( & mut buf) ) , write3. len( ) ) ;
1958+ assert_eq ! ( str :: from_utf8( & buf[ ..write3. len( ) ] ) , Ok ( write3) ) ;
1959+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 14 ) ;
1960+ assert_eq ! ( check!( read. read_at( & mut buf, 0 ) ) , content. len( ) ) ;
1961+ assert_eq ! ( str :: from_utf8( & buf[ ..content. len( ) ] ) , Ok ( content) ) ;
1962+ assert_eq ! ( check!( read. seek( SeekFrom :: Current ( 0 ) ) ) , 14 ) ;
1963+ }
1964+ check ! ( fs:: remove_file( & filename) ) ;
1965+ }
1966+
18961967 #[ test]
18971968 fn file_test_stat_is_correct_on_is_file ( ) {
18981969 let tmpdir = tmpdir ( ) ;
0 commit comments