alloc/io/copy.rs
1mod generic;
2mod specialization;
3
4use self::generic::generic_copy;
5#[doc(hidden)]
6#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
7pub use self::specialization::SpecCopy;
8use self::specialization::SpecCopyInner;
9use crate::io::{Read, Result, Write};
10
11/// Used as a part of [copy specialization](SpecCopy) to communicate how many bytes
12/// were copied, and whether copying is done.
13///
14/// * [`Ended(n)`](CopyState::Ended) indicates copying completed, moving a total
15/// of `n` bytes.
16/// * [`Fallback(n)`](CopyState::Fallback) indicates copying is _might_ not be
17/// complete, and so far `n` bytes have been copied using specialization.
18/// The remaining must be copied using a fallback implementation.
19///
20/// If a particular `Read` and `Write` combination do not implement a specialized
21/// copy routine, the specialized function will return `Fallback(0)`.
22#[derive(Debug)]
23#[doc(hidden)]
24#[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")]
25pub enum CopyState {
26 Ended(u64),
27 Fallback(u64),
28}
29
30/// Copies the entire contents of a reader into a writer.
31///
32/// This function will continuously read data from `reader` and then
33/// write it into `writer` in a streaming fashion until `reader`
34/// returns EOF.
35///
36/// On success, the total number of bytes that were copied from
37/// `reader` to `writer` is returned.
38///
39/// If you want to copy the contents of one file to another and you’re
40/// working with filesystem paths, see the [`fs::copy`] function.
41///
42// FIXME(#74481): Hard-links required to link from `alloc` to `std`
43/// [`fs::copy`]: ../../std/fs/fn.copy.html
44///
45/// # Errors
46///
47/// This function will return an error immediately if any call to [`read`] or
48/// [`write`] returns an error. All instances of [`ErrorKind::Interrupted`] are
49/// handled by this function and the underlying operation is retried.
50///
51/// [`read`]: Read::read
52/// [`write`]: Write::write
53/// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted
54///
55/// # Examples
56///
57/// ```
58/// use std::io;
59///
60/// fn main() -> io::Result<()> {
61/// let mut reader: &[u8] = b"hello";
62/// let mut writer: Vec<u8> = vec![];
63///
64/// io::copy(&mut reader, &mut writer)?;
65///
66/// assert_eq!(&b"hello"[..], &writer[..]);
67/// Ok(())
68/// }
69/// ```
70///
71/// # Platform-specific behavior
72///
73/// On Linux (including Android), this function uses `copy_file_range(2)`,
74/// `sendfile(2)` or `splice(2)` syscalls to move data directly between file
75/// descriptors if possible.
76///
77/// Note that platform-specific behavior may change in the future.
78#[stable(feature = "rust1", since = "1.0.0")]
79pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
80where
81 R: Read,
82 W: Write,
83{
84 match SpecCopyInner::copy(reader, writer)? {
85 CopyState::Ended(copied) => Ok(copied),
86 CopyState::Fallback(copied) => {
87 generic_copy(reader, writer).map(|additional| copied + additional)
88 }
89 }
90}