@@ -43,6 +43,7 @@ use crate::task::{Context, Poll};
4343/// #
4444/// # Ok(()) }) }
4545/// ```
46+ #[ cfg( any( feature = "docs" , not( feature = "unstable" ) ) ) ]
4647pub async fn copy < R , W > ( reader : & mut R , writer : & mut W ) -> io:: Result < u64 >
4748where
4849 R : Read + Unpin + ?Sized ,
9192 } ;
9293 future. await
9394}
95+
96+ /// Copies the entire contents of a reader into a writer.
97+ ///
98+ /// This function will continuously read data from `reader` and then
99+ /// write it into `writer` in a streaming fashion until `reader`
100+ /// returns EOF.
101+ ///
102+ /// On success, the total number of bytes that were copied from
103+ /// `reader` to `writer` is returned.
104+ ///
105+ /// If you’re wanting to copy the contents of one file to another and you’re
106+ /// working with filesystem paths, see the [`fs::copy`] function.
107+ ///
108+ /// This function is an async version of [`std::io::copy`].
109+ ///
110+ /// [`std::io::copy`]: https://doc.rust-lang.org/std/io/fn.copy.html
111+ /// [`fs::copy`]: ../fs/fn.copy.html
112+ ///
113+ /// # Errors
114+ ///
115+ /// This function will return an error immediately if any call to `read` or
116+ /// `write` returns an error. All instances of `ErrorKind::Interrupted` are
117+ /// handled by this function and the underlying operation is retried.
118+ ///
119+ /// # Examples
120+ ///
121+ /// ```
122+ /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
123+ /// #
124+ /// use async_std::io;
125+ ///
126+ /// let mut reader: &[u8] = b"hello";
127+ /// let mut writer = io::stdout();
128+ ///
129+ /// io::copy(&mut reader, &mut writer).await?;
130+ /// #
131+ /// # Ok(()) }) }
132+ /// ```
133+ #[ cfg( all( feature = "unstable" , not( feature = "docs" ) ) ) ]
134+ pub async fn copy < R , W > ( reader : R , writer : W ) -> io:: Result < u64 >
135+ where
136+ R : Read + Unpin ,
137+ W : Write + Unpin ,
138+ {
139+ pin_project ! {
140+ struct CopyFuture <R , W > {
141+ #[ pin]
142+ reader: R ,
143+ #[ pin]
144+ writer: W ,
145+ amt: u64 ,
146+ }
147+ }
148+
149+ impl < R , W > Future for CopyFuture < R , W >
150+ where
151+ R : BufRead ,
152+ W : Write + Unpin ,
153+ {
154+ type Output = io:: Result < u64 > ;
155+
156+ fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
157+ let mut this = self . project ( ) ;
158+ loop {
159+ let buffer = futures_core:: ready!( this. reader. as_mut( ) . poll_fill_buf( cx) ) ?;
160+ if buffer. is_empty ( ) {
161+ futures_core:: ready!( this. writer. as_mut( ) . poll_flush( cx) ) ?;
162+ return Poll :: Ready ( Ok ( * this. amt ) ) ;
163+ }
164+
165+ let i = futures_core:: ready!( this. writer. as_mut( ) . poll_write( cx, buffer) ) ?;
166+ if i == 0 {
167+ return Poll :: Ready ( Err ( io:: ErrorKind :: WriteZero . into ( ) ) ) ;
168+ }
169+ * this. amt += i as u64 ;
170+ this. reader . as_mut ( ) . consume ( i) ;
171+ }
172+ }
173+ }
174+
175+ let future = CopyFuture {
176+ reader : BufReader :: new ( reader) ,
177+ writer,
178+ amt : 0 ,
179+ } ;
180+ future. await
181+ }
0 commit comments