| mod generic; |
| mod specialization; |
| |
| use self::generic::generic_copy; |
| #[doc(hidden)] |
| #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] |
| pub use self::specialization::SpecCopy; |
| use self::specialization::SpecCopyInner; |
| use crate::io::{Read, Result, Write}; |
| |
| /// Used as a part of [copy specialization](SpecCopy) to communicate how many bytes |
| /// were copied, and whether copying is done. |
| /// |
| /// * [`Ended(n)`](CopyState::Ended) indicates copying completed, moving a total |
| /// of `n` bytes. |
| /// * [`Fallback(n)`](CopyState::Fallback) indicates copying is _might_ not be |
| /// complete, and so far `n` bytes have been copied using specialization. |
| /// The remaining must be copied using a fallback implementation. |
| /// |
| /// If a particular `Read` and `Write` combination do not implement a specialized |
| /// copy routine, the specialized function will return `Fallback(0)`. |
| #[derive(Debug)] |
| #[doc(hidden)] |
| #[unstable(feature = "core_io_internals", reason = "exposed only for libstd", issue = "none")] |
| pub enum CopyState { |
| Ended(u64), |
| Fallback(u64), |
| } |
| |
| /// Copies the entire contents of a reader into a writer. |
| /// |
| /// This function will continuously read data from `reader` and then |
| /// write it into `writer` in a streaming fashion until `reader` |
| /// returns EOF. |
| /// |
| /// On success, the total number of bytes that were copied from |
| /// `reader` to `writer` is returned. |
| /// |
| /// If you want to copy the contents of one file to another and you’re |
| /// working with filesystem paths, see the [`fs::copy`] function. |
| /// |
| // FIXME(#74481): Hard-links required to link from `alloc` to `std` |
| /// [`fs::copy`]: ../../std/fs/fn.copy.html |
| /// |
| /// # Errors |
| /// |
| /// This function will return an error immediately if any call to [`read`] or |
| /// [`write`] returns an error. All instances of [`ErrorKind::Interrupted`] are |
| /// handled by this function and the underlying operation is retried. |
| /// |
| /// [`read`]: Read::read |
| /// [`write`]: Write::write |
| /// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::io; |
| /// |
| /// fn main() -> io::Result<()> { |
| /// let mut reader: &[u8] = b"hello"; |
| /// let mut writer: Vec<u8> = vec![]; |
| /// |
| /// io::copy(&mut reader, &mut writer)?; |
| /// |
| /// assert_eq!(&b"hello"[..], &writer[..]); |
| /// Ok(()) |
| /// } |
| /// ``` |
| /// |
| /// # Platform-specific behavior |
| /// |
| /// On Linux (including Android), this function uses `copy_file_range(2)`, |
| /// `sendfile(2)` or `splice(2)` syscalls to move data directly between file |
| /// descriptors if possible. |
| /// |
| /// Note that platform-specific behavior may change in the future. |
| #[stable(feature = "rust1", since = "1.0.0")] |
| pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64> |
| where |
| R: Read, |
| W: Write, |
| { |
| match SpecCopyInner::copy(reader, writer)? { |
| CopyState::Ended(copied) => Ok(copied), |
| CopyState::Fallback(copied) => { |
| generic_copy(reader, writer).map(|additional| copied + additional) |
| } |
| } |
| } |