@@ -27,6 +27,58 @@ pub trait FileExt {
2727 /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read_vectored
2828 fn read_at ( & self , bufs : & mut [ IoSliceMut < ' _ > ] , offset : u64 ) -> io:: Result < usize > ;
2929
30+ /// Reads the exact number of byte required to fill `buf` from the given offset.
31+ ///
32+ /// The offset is relative to the start of the file and thus independent
33+ /// from the current cursor.
34+ ///
35+ /// The current file cursor is not affected by this function.
36+ ///
37+ /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
38+ ///
39+ /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
40+ /// [`read_at`]: #tymethod.read_at
41+ ///
42+ /// # Errors
43+ ///
44+ /// If this function encounters an error of the kind
45+ /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
46+ /// will continue.
47+ ///
48+ /// If this function encounters an "end of file" before completely filling
49+ /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
50+ /// The contents of `buf` are unspecified in this case.
51+ ///
52+ /// If any other read error is encountered then this function immediately
53+ /// returns. The contents of `buf` are unspecified in this case.
54+ ///
55+ /// If this function returns an error, it is unspecified how many bytes it
56+ /// has read, but it will never read more than would be necessary to
57+ /// completely fill the buffer.
58+ ///
59+ /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
60+ /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
61+ #[ stable( feature = "rw_exact_all_at" , since = "1.33.0" ) ]
62+ fn read_exact_at ( & self , mut buf : & mut [ u8 ] , mut offset : u64 ) -> io:: Result < ( ) > {
63+ while !buf. is_empty ( ) {
64+ match self . read_at ( buf, offset) {
65+ Ok ( 0 ) => break ,
66+ Ok ( n) => {
67+ let tmp = buf;
68+ buf = & mut tmp[ n..] ;
69+ offset += n as u64 ;
70+ }
71+ Err ( ref e) if e. kind ( ) == io:: ErrorKind :: Interrupted => { }
72+ Err ( e) => return Err ( e) ,
73+ }
74+ }
75+ if !buf. is_empty ( ) {
76+ Err ( io:: Error :: new ( io:: ErrorKind :: UnexpectedEof , "failed to fill whole buffer" ) )
77+ } else {
78+ Ok ( ( ) )
79+ }
80+ }
81+
3082 /// Writes a number of bytes starting from a given offset.
3183 ///
3284 /// Returns the number of bytes written.
@@ -45,6 +97,48 @@ pub trait FileExt {
4597 /// [`File::write`]: ../../../../std/fs/struct.File.html#method.write_vectored
4698 fn write_at ( & self , bufs : & [ IoSlice < ' _ > ] , offset : u64 ) -> io:: Result < usize > ;
4799
100+ /// Attempts to write an entire buffer starting from a given offset.
101+ ///
102+ /// The offset is relative to the start of the file and thus independent
103+ /// from the current cursor.
104+ ///
105+ /// The current file cursor is not affected by this function.
106+ ///
107+ /// This method will continuously call [`write_at`] until there is no more data
108+ /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
109+ /// returned. This method will not return until the entire buffer has been
110+ /// successfully written or such an error occurs. The first error that is
111+ /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
112+ /// returned.
113+ ///
114+ /// # Errors
115+ ///
116+ /// This function will return the first error of
117+ /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
118+ ///
119+ /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
120+ /// [`write_at`]: #tymethod.write_at
121+ #[ stable( feature = "rw_exact_all_at" , since = "1.33.0" ) ]
122+ fn write_all_at ( & self , mut buf : & [ u8 ] , mut offset : u64 ) -> io:: Result < ( ) > {
123+ while !buf. is_empty ( ) {
124+ match self . write_at ( buf, offset) {
125+ Ok ( 0 ) => {
126+ return Err ( io:: Error :: new (
127+ io:: ErrorKind :: WriteZero ,
128+ "failed to write whole buffer" ,
129+ ) ) ;
130+ }
131+ Ok ( n) => {
132+ buf = & buf[ n..] ;
133+ offset += n as u64
134+ }
135+ Err ( ref e) if e. kind ( ) == io:: ErrorKind :: Interrupted => { }
136+ Err ( e) => return Err ( e) ,
137+ }
138+ }
139+ Ok ( ( ) )
140+ }
141+
48142 /// Returns the current position within the file.
49143 ///
50144 /// This corresponds to the `fd_tell` syscall and is similar to
0 commit comments