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
use super::{BufWriter, ErrorKind, Read, ReadBuf, 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(())
/// }
/// ```
///
///
///
///
#[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 = ReadBuf::uninit(buf.spare_capacity_mut());

            // SAFETY: init 要么是 0,要么是上一次迭代的 initialized_len
            unsafe {
                read_buf.assume_init(init);
            }

            if read_buf.capacity() >= DEFAULT_BUF_SIZE {
                match reader.read_buf(&mut read_buf) {
                    Ok(()) => {
                        let bytes_read = read_buf.filled_len();

                        if bytes_read == 0 {
                            return Ok(len);
                        }

                        init = read_buf.initialized_len() - bytes_read;

                        // SAFETY: ReadBuf 保证所有填充的字节都是初始化的
                        unsafe { buf.set_len(buf.len() + bytes_read) };
                        len += bytes_read as u64;
                        // 如果缓冲区仍然有足够的容量,则重新读取,如 BufWriter 本身那样。如果 reader 返回短读,则会发生这种情况
                        //
                        continue;
                    }
                    Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
                    Err(e) => return Err(e),
                }
            }

            writer.flush_buf()?;
        }
    }
}

fn stack_buffer_copy<R: Read + ?Sized, W: Write + ?Sized>(
    reader: &mut R,
    writer: &mut W,
) -> Result<u64> {
    let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE];
    let mut buf = ReadBuf::uninit(&mut buf);

    let mut len = 0;

    loop {
        match reader.read_buf(&mut buf) {
            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)
}