ckb_rust_std/io/
copy.rs

1use super::{BorrowedBuf, Read, Result, Write, DEFAULT_BUF_SIZE};
2use core::mem::MaybeUninit;
3/// Copies the entire contents of a reader into a writer.
4///
5/// This function will continuously read data from `reader` and then
6/// write it into `writer` in a streaming fashion until `reader`
7/// returns EOF.
8///
9/// On success, the total number of bytes that were copied from
10/// `reader` to `writer` is returned.
11///
12/// If you want to copy the contents of one file to another and you’re
13/// working with filesystem paths, see the [`fs::copy`] function.
14///
15/// [`fs::copy`]: crate::fs::copy
16///
17/// # Errors
18///
19/// This function will return an error immediately if any call to [`read`] or
20/// [`write`] returns an error. All instances of [`ErrorKind::Interrupted`] are
21/// handled by this function and the underlying operation is retried.
22///
23/// [`read`]: Read::read
24/// [`write`]: Write::write
25/// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted
26///
27/// # Examples
28///
29/// ```
30/// use std::io;
31///
32/// fn main() -> io::Result<()> {
33///     let mut reader: &[u8] = b"hello";
34///     let mut writer: Vec<u8> = vec![];
35///
36///     io::copy(&mut reader, &mut writer)?;
37///
38///     assert_eq!(&b"hello"[..], &writer[..]);
39///     Ok(())
40/// }
41/// ```
42///
43/// # Platform-specific behavior
44///
45/// On Linux (including Android), this function uses `copy_file_range(2)`,
46/// `sendfile(2)` or `splice(2)` syscalls to move data directly between file
47/// descriptors if possible.
48///
49/// Note that platform-specific behavior [may change in the future][changes].
50///
51/// [changes]: crate::io#platform-specific-behavior
52pub fn copy<R: ?Sized + Read, W: ?Sized + Write>(reader: &mut R, writer: &mut W) -> Result<u64> {
53    stack_buffer_copy(reader, writer)
54}
55
56pub fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
57    reader: &mut R,
58    writer: &mut W,
59) -> Result<u64> {
60    let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE];
61    let mut buf: BorrowedBuf<'_> = buf.into();
62    let mut len = 0;
63    loop {
64        match reader.read_buf(buf.unfilled()) {
65            Ok(()) => {}
66            Err(e) if e.is_interrupted() => continue,
67            Err(e) => return Err(e),
68        };
69        if buf.filled().is_empty() {
70            break;
71        }
72        len += buf.filled().len() as u64;
73        writer.write_all(buf.filled())?;
74        buf.clear();
75    }
76    Ok(len)
77}