]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/adapters/by_ref_sized.rs
:arrow_up: rust-analyzer
[rust.git] / library / core / src / iter / adapters / by_ref_sized.rs
1 use crate::{
2     const_closure::ConstFnMutClosure,
3     ops::{NeverShortCircuit, Try},
4 };
5
6 /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
7 ///
8 /// Ideally this will no longer be required, eventually, but as can be seen in
9 /// the benchmarks (as of Feb 2022 at least) `by_ref` can have performance cost.
10 #[unstable(feature = "std_internals", issue = "none")]
11 #[derive(Debug)]
12 pub struct ByRefSized<'a, I>(pub &'a mut I);
13
14 // The following implementations use UFCS-style, rather than trusting autoderef,
15 // to avoid accidentally calling the `&mut Iterator` implementations.
16
17 #[unstable(feature = "std_internals", issue = "none")]
18 impl<I: Iterator> Iterator for ByRefSized<'_, I> {
19     type Item = I::Item;
20
21     #[inline]
22     fn next(&mut self) -> Option<Self::Item> {
23         I::next(self.0)
24     }
25
26     #[inline]
27     fn size_hint(&self) -> (usize, Option<usize>) {
28         I::size_hint(self.0)
29     }
30
31     #[inline]
32     fn advance_by(&mut self, n: usize) -> Result<(), usize> {
33         I::advance_by(self.0, n)
34     }
35
36     #[inline]
37     fn nth(&mut self, n: usize) -> Option<Self::Item> {
38         I::nth(self.0, n)
39     }
40
41     #[inline]
42     fn fold<B, F>(self, init: B, mut f: F) -> B
43     where
44         F: FnMut(B, Self::Item) -> B,
45     {
46         // `fold` needs ownership, so this can't forward directly.
47         I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
48             .0
49     }
50
51     #[inline]
52     fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
53     where
54         F: FnMut(B, Self::Item) -> R,
55         R: Try<Output = B>,
56     {
57         I::try_fold(self.0, init, f)
58     }
59 }
60
61 #[unstable(feature = "std_internals", issue = "none")]
62 impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
63     #[inline]
64     fn next_back(&mut self) -> Option<Self::Item> {
65         I::next_back(self.0)
66     }
67
68     #[inline]
69     fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
70         I::advance_back_by(self.0, n)
71     }
72
73     #[inline]
74     fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
75         I::nth_back(self.0, n)
76     }
77
78     #[inline]
79     fn rfold<B, F>(self, init: B, mut f: F) -> B
80     where
81         F: FnMut(B, Self::Item) -> B,
82     {
83         // `rfold` needs ownership, so this can't forward directly.
84         I::try_rfold(
85             self.0,
86             init,
87             ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
88         )
89         .0
90     }
91
92     #[inline]
93     fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
94     where
95         F: FnMut(B, Self::Item) -> R,
96         R: Try<Output = B>,
97     {
98         I::try_rfold(self.0, init, f)
99     }
100 }