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() }
}
}