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
use crate::num::NonZeroUsize;
use crate::ops::{NeverShortCircuit, Try};

/// 与 `Iterator::by_ref` 类似,但需要 `Sized` 才能转发泛型。
///
/// 理想情况下,最终将不再需要这样做,但从基准测试中可以看出 (至少截至 2022 年 2 月) `by_ref` 可能会有性能成本。
///
#[unstable(feature = "std_internals", issue = "none")]
#[derive(Debug)]
pub struct ByRefSized<'a, I>(pub &'a mut I);

// 以下实现使用 UFCS 样式,而不是信任 autoderef,以避免意外调用 `&mut Iterator` 实现。
//

#[unstable(feature = "std_internals", issue = "none")]
impl<I: Iterator> Iterator for ByRefSized<'_, I> {
    type Item = I::Item;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        I::next(self.0)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        I::size_hint(self.0)
    }

    #[inline]
    fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
        I::advance_by(self.0, n)
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        I::nth(self.0, n)
    }

    #[inline]
    fn fold<B, F>(self, init: B, f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B,
    {
        // `fold` 需要所有权,所以不能直接转发。
        I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
    }

    #[inline]
    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
    where
        F: FnMut(B, Self::Item) -> R,
        R: Try<Output = B>,
    {
        I::try_fold(self.0, init, f)
    }
}

#[unstable(feature = "std_internals", issue = "none")]
impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
    #[inline]
    fn next_back(&mut self) -> Option<Self::Item> {
        I::next_back(self.0)
    }

    #[inline]
    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
        I::advance_back_by(self.0, n)
    }

    #[inline]
    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
        I::nth_back(self.0, n)
    }

    #[inline]
    fn rfold<B, F>(self, init: B, f: F) -> B
    where
        F: FnMut(B, Self::Item) -> B,
    {
        // `rfold` 需要所有权,所以不能直接转发。
        I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
    }

    #[inline]
    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
    where
        F: FnMut(B, Self::Item) -> R,
        R: Try<Output = B>,
    {
        I::try_rfold(self.0, init, f)
    }
}