Skip to content

Commit 9e185f1

Browse files
author
Stjepan Glavina
authored
Unstable feature: copy takes arguments by value (#471)
* Unstable feature: copy takes arguments by value * Fix feature flags
1 parent 89d6116 commit 9e185f1

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

src/io/copy.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use crate::task::{Context, Poll};
4343
/// #
4444
/// # Ok(()) }) }
4545
/// ```
46+
#[cfg(any(feature = "docs", not(feature = "unstable")))]
4647
pub async fn copy<R, W>(reader: &mut R, writer: &mut W) -> io::Result<u64>
4748
where
4849
R: Read + Unpin + ?Sized,
@@ -91,3 +92,90 @@ where
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

Comments
 (0)