1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
use super::{BorrowedBuf, BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE};
use crate::mem::MaybeUninit;
/// 将 reader 的全部内容复制到 writer 中。
///
/// 此函数将连续从 `reader` 读取数据,然后以流方式将其写入 `writer`,直到 `reader` 返回 EOF。
///
/// 成功后,将返回从 `reader` 复制到 `writer` 的字节总数。
///
/// 如果要将一个文件的内容复制到另一个文件并且您正在使用文件系统路径,请参见 [`fs::copy`] 函数。
///
/// [`fs::copy`]: crate::fs::copy
///
/// # Errors
///
/// 如果对 [`read`] 或 [`write`] 的任何调用返回错误,则此函数将立即返回错误。
/// 此函数将处理 [`ErrorKind::Interrupted`] 的所有实例,并重试底层操作。
///
/// [`read`]: Read::read
/// [`write`]: Write::write
///
/// # 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(())
/// }
/// ```
///
/// # 特定于平台的行为
///
/// 在 Linux (包括 Android) 上,如果可能的话,此函数使用 `copy_file_range(2)`、`sendfile(2)` 或 `splice(2)` 系统调用在文件描述符之间直接移动数据。
///
///
/// 请注意,特定于平台的行为 [将来可能会改变][changes]。
///
/// [changes]: crate::io#platform-specific-behavior
///
///
///
///
///
///
#[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,
{
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "android"))] {
crate::sys::kernel_copy::copy_spec(reader, writer)
} else {
generic_copy(reader, writer)
}
}
}
/// `io::copy` 的用户空间读写循环实现,当特定于操作系统的专门用于复制卸载的专业化不可用或不适用时,将使用该 `io::copy`。
///
pub(crate) fn generic_copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64>
where
R: Read,
W: Write,
{
BufferedCopySpec::copy_to(reader, writer)
}
/// 使用栈缓冲区或重用 BufWriter 的内部缓冲区的读写循环的特殊化
///
trait BufferedCopySpec: Write {
fn copy_to<R: Read + ?Sized>(reader: &mut R, writer: &mut Self) -> Result<u64>;
}
impl<W: Write + ?Sized> BufferedCopySpec for W {
default fn copy_to<R: Read + ?Sized>(reader: &mut R, writer: &mut Self) -> Result<u64> {
stack_buffer_copy(reader, writer)
}
}
impl<I: Write> BufferedCopySpec for BufWriter<I> {
fn copy_to<R: Read + ?Sized>(reader: &mut R, writer: &mut Self) -> Result<u64> {
if writer.capacity() < DEFAULT_BUF_SIZE {
return stack_buffer_copy(reader, writer);
}
let mut len = 0;
let mut init = 0;
loop {
let buf = writer.buffer_mut();
let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into();
unsafe {
// SAFETY: init 为 0 或上一次迭代的 init_len。
read_buf.set_init(init);
}
if read_buf.capacity() >= DEFAULT_BUF_SIZE {
let mut cursor = read_buf.unfilled();
match reader.read_buf(cursor.reborrow()) {
Ok(()) => {
let bytes_read = cursor.written();
if bytes_read == 0 {
return Ok(len);
}
init = read_buf.init_len() - bytes_read;
len += bytes_read as u64;
// SAFETY: BorrowedBuf 保证它所有的填充字节都是 init
unsafe { buf.set_len(buf.len() + bytes_read) };
// 如果缓冲区仍然有足够的容量,则重新读取,如 BufWriter 本身那样。如果 reader 返回短读,则会发生这种情况
//
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
} else {
writer.flush_buf()?;
init = 0;
}
}
}
}
fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
reader: &mut R,
writer: &mut W,
) -> Result<u64> {
let buf: &mut [_] = &mut [MaybeUninit::uninit(); DEFAULT_BUF_SIZE];
let mut buf: BorrowedBuf<'_> = buf.into();
let mut len = 0;
loop {
match reader.read_buf(buf.unfilled()) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Err(e),
};
if buf.filled().is_empty() {
break;
}
len += buf.filled().len() as u64;
writer.write_all(buf.filled())?;
buf.clear();
}
Ok(len)
}