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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#![unstable(feature = "read_buf", issue = "78485")]

#[cfg(test)]
mod tests;

use crate::cmp;
use crate::fmt::{self, Debug, Formatter};
use crate::mem::MaybeUninit;

/// 字节缓冲区的包装器,它被增量填充和初始化。
///
/// 这种类型是一种 "double cursor"。
/// 它跟踪缓冲区中的三个区域:缓冲区开头的区域已被逻辑填充数据,已在某个时刻初始化但尚未逻辑填充的区域,以及完全未初始化的末尾区域。
/// 填充区域保证是初始化区域的子集。
///
/// 总之,缓冲区的内容可以可视化为:
///
/// ```not_rust
/// [             capacity              ]
/// [ filled |         unfilled         ]
/// [    initialized    | uninitialized ]
/// ```
pub struct ReadBuf<'a> {
    buf: &'a mut [MaybeUninit<u8>],
    filled: usize,
    initialized: usize,
}

impl Debug for ReadBuf<'_> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_struct("ReadBuf")
            .field("init", &self.initialized())
            .field("filled", &self.filled)
            .field("capacity", &self.capacity())
            .finish()
    }
}

impl<'a> ReadBuf<'a> {
    /// 从完全初始化的缓冲区创建一个新的 `ReadBuf`。
    #[inline]
    pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> {
        let len = buf.len();

        ReadBuf {
            // SAFETY: 初始化数据永远不会变为未初始化是 ReadBuf 的不变量
            buf: unsafe { (buf as *mut [u8]).as_uninit_slice_mut().unwrap() },
            filled: 0,
            initialized: len,
        }
    }

    /// 从完全未初始化的缓冲区创建一个新的 `ReadBuf`。
    ///
    /// 如果已知缓冲区的一部分已经初始化,请使用 `assume_init`。
    #[inline]
    pub fn uninit(buf: &'a mut [MaybeUninit<u8>]) -> ReadBuf<'a> {
        ReadBuf { buf, filled: 0, initialized: 0 }
    }

    /// 返回缓冲区的总容量。
    #[inline]
    pub fn capacity(&self) -> usize {
        self.buf.len()
    }

    /// 返回对缓冲区填充部分的共享引用。
    #[inline]
    pub fn filled(&self) -> &[u8] {
        // SAFETY: 我们只对缓冲区的填充部分进行切片,这总是有效的
        unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) }
    }

    /// 返回对缓冲区已填充部分的可变引用。
    #[inline]
    pub fn filled_mut(&mut self) -> &mut [u8] {
        // SAFETY: 我们只对缓冲区的填充部分进行切片,这总是有效的
        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) }
    }

    /// 返回对缓冲区初始化部分的共享引用。
    ///
    /// 这包括填充的部分。
    #[inline]
    pub fn initialized(&self) -> &[u8] {
        // SAFETY: 我们只对缓冲区的初始化部分进行切片,这始终是有效的
        unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.initialized]) }
    }

    /// 返回对缓冲区初始化部分的可变引用。
    ///
    /// 这包括填充的部分。
    #[inline]
    pub fn initialized_mut(&mut self) -> &mut [u8] {
        // SAFETY: 我们只对缓冲区的初始化部分进行切片,这始终是有效的
        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.initialized]) }
    }

    /// 返回对缓冲区未填充部分的可变引用,而不确保缓冲区已完全初始化。
    ///
    ///
    /// # Safety
    ///
    /// 调用者不得取消已初始化的缓冲区部分的初始化。
    #[inline]
    pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<u8>] {
        &mut self.buf[self.filled..]
    }

    /// 返回对缓冲区未初始化部分的可变引用。
    ///
    /// 取消初始化这些字节中的任何一个都是安全的。
    #[inline]
    pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit<u8>] {
        &mut self.buf[self.initialized..]
    }

    /// 返回对缓冲区未填充部分的可变引用,确保它已完全初始化。
    ///
    /// 由于 `ReadBuf` 跟踪已初始化的缓冲区区域,因此在第一次使用后实际上是 "free"。
    ///
    #[inline]
    pub fn initialize_unfilled(&mut self) -> &mut [u8] {
        // 应该优化断言
        self.initialize_unfilled_to(self.remaining())
    }

    /// 返回对缓冲区未填充部分的第一个 `n` 字节的可变引用,确保它已完全初始化。
    ///
    ///
    /// # Panics
    ///
    /// 如果 `self.remaining()` 小于 `n`,就会出现 panics。
    #[inline]
    pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] {
        assert!(self.remaining() >= n);

        let extra_init = self.initialized - self.filled;
        // 如果我们没有足够的初始化,就归零
        if n > extra_init {
            let uninit = n - extra_init;
            let unfilled = &mut self.uninitialized_mut()[0..uninit];

            for byte in unfilled.iter_mut() {
                byte.write(0);
            }

            // SAFETY: 我们刚刚初始化了 uninit 字节,前面的字节已经初始化了
            unsafe {
                self.assume_init(n);
            }
        }

        let filled = self.filled;

        &mut self.initialized_mut()[filled..filled + n]
    }

    /// 返回切片末尾尚未填充的字节数。
    #[inline]
    pub fn remaining(&self) -> usize {
        self.capacity() - self.filled
    }

    /// 清除缓冲区,将填充区域重置为空。
    ///
    /// 初始化的字节数不变,缓冲区的内容也不变。
    #[inline]
    pub fn clear(&mut self) {
        self.set_filled(0); // `set_filled` 中的断言优化掉了
    }

    /// 增加缓冲区填充区域的大小。
    ///
    /// 初始化字节数不变。
    ///
    /// # Panics
    ///
    /// 如果缓冲区的填充区域大于初始化区域,就会出现 panics。
    #[inline]
    pub fn add_filled(&mut self, n: usize) {
        self.set_filled(self.filled + n);
    }

    /// 设置缓冲区填充区域的大小。
    ///
    /// 初始化字节数不变。
    ///
    /// 请注意,除了增加缓冲区的填充区域 (例如,通过就地压缩数据的 `Read` 实现) 之外,这还可用于*缩小*缓冲区的填充区域。
    ///
    ///
    /// # Panics
    ///
    /// 如果缓冲区的填充区域大于初始化区域,就会出现 panics。
    #[inline]
    pub fn set_filled(&mut self, n: usize) {
        assert!(n <= self.initialized);

        self.filled = n;
    }

    /// 断言缓冲区的前 `n` 个未填充字节已初始化。
    ///
    /// `ReadBuf` 假定字节永远不会被反初始化,因此当使用少于已知已初始化字节的字节调用此方法时,不会执行任何操作。
    ///
    ///
    /// # Safety
    ///
    /// 调用者必须确保缓冲区的前 `n` 个未填充字节已经初始化。
    #[inline]
    pub unsafe fn assume_init(&mut self, n: usize) {
        self.initialized = cmp::max(self.initialized, self.filled + n);
    }

    /// 将数据追加到缓冲区,推进写入位置,也可能推进初始化位置。
    ///
    /// # Panics
    ///
    /// 如果 `self.remaining()` 小于 `buf.len()`,就会出现 panics。
    #[inline]
    pub fn append(&mut self, buf: &[u8]) {
        assert!(self.remaining() >= buf.len());

        // SAFETY: 我们不会取消初始化切片的任何元素
        unsafe {
            MaybeUninit::write_slice(&mut self.unfilled_mut()[..buf.len()], buf);
        }

        // SAFETY: 我们只是将 buf 的全部内容添加到了填充部分。
        unsafe { self.assume_init(buf.len()) }
        self.add_filled(buf.len());
    }

    /// 返回已填充的字节数。
    #[inline]
    pub fn filled_len(&self) -> usize {
        self.filled
    }

    /// 返回已初始化的字节数。
    #[inline]
    pub fn initialized_len(&self) -> usize {
        self.initialized
    }
}