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
use crate::iter::{TrustedLen, UncheckedIterator};
use crate::mem::ManuallyDrop;
use crate::ptr::drop_in_place;
use crate::slice;

/// `array.into_iter().for_each(func)` 的情境优化版本。
///
/// [`crate::IntoIter`] 在您需要一个拥有所有权的迭代器时非常有用,但是像这样将整个数组*内部*存储在迭代器中有时会使代码变得悲观。
/// 值得注意的是,它可能比您真正想要移动的字节更多,并且因为数组访问其中的索引,所以 SRoA 比只包含几个指针的迭代器更难优化类型。
///
///
/// 因此这个函数存在,它提供了一种方法来*移动*使用小迭代器访问数组的元素 -- 不比切片迭代器大。
///
/// 函数 - taking-a - 闭包结构体使它变得安全,因为它可以防止,调用者,查看已经 - 丢弃的元素。
///
///
///
///
pub(crate) fn drain_array_with<T, R, const N: usize>(
    array: [T; N],
    func: impl for<'a> FnOnce(Drain<'a, T>) -> R,
) -> R {
    let mut array = ManuallyDrop::new(array);
    // SAFETY: 既然当地人不会抛弃它,那么构建 `Drain` 就可以了。
    let drain = Drain(array.iter_mut());
    func(drain)
}

/// 请参见 [`drain_array_with`]-- 这只是 `pub(crate)`,因此可以在该方法的签名中提及它。
/// (否则它会命中 `E0446`。)
// INVARIANT: 抛弃内部迭代器的其余部分是可以的。
pub(crate) struct Drain<'a, T>(slice::IterMut<'a, T>);

impl<T> Drop for Drain<'_, T> {
    fn drop(&mut self) {
        // SAFETY: 通过类型不,变体,我们可以放弃所有这些。
        unsafe { drop_in_place(self.0.as_mut_slice()) }
    }
}

impl<T> Iterator for Drain<'_, T> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        let p: *const T = self.0.next()?;
        // SAFETY: 迭代器已经提前了,所以我们以后不会丢弃它。
        Some(unsafe { p.read() })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let n = self.len();
        (n, Some(n))
    }
}

impl<T> ExactSizeIterator for Drain<'_, T> {
    #[inline]
    fn len(&self) -> usize {
        self.0.len()
    }
}

// SAFETY: 这是切片迭代器的 1:1 包装器,它也是 `TrustedLen`。
unsafe impl<T> TrustedLen for Drain<'_, T> {}

impl<T> UncheckedIterator for Drain<'_, T> {
    unsafe fn next_unchecked(&mut self) -> T {
        // SAFETY: `Drain` 与内部迭代器是 1:1,所以如果调用者承诺还有一个元素,则内部迭代器也有一个。
        //
        let p: *const T = unsafe { self.0.next_unchecked() };
        // SAFETY: 迭代器已经提前了,所以我们以后不会丢弃它。
        unsafe { p.read() }
    }
}