|
1 | 1 | use crate::cmp;
|
2 |
| -use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen}; |
| 2 | +use crate::iter::{ |
| 3 | + adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess, |
| 4 | +}; |
3 | 5 | use crate::num::NonZeroUsize;
|
4 | 6 | use crate::ops::{ControlFlow, Try};
|
5 | 7 |
|
@@ -98,26 +100,18 @@ where
|
98 | 100 | }
|
99 | 101 | }
|
100 | 102 |
|
101 |
| - impl_fold_via_try_fold! { fold -> try_fold } |
102 |
| - |
103 | 103 | #[inline]
|
104 |
| - fn for_each<F: FnMut(Self::Item)>(mut self, f: F) { |
105 |
| - // The default implementation would use a unit accumulator, so we can |
106 |
| - // avoid a stateful closure by folding over the remaining number |
107 |
| - // of items we wish to return instead. |
108 |
| - fn check<'a, Item>( |
109 |
| - mut action: impl FnMut(Item) + 'a, |
110 |
| - ) -> impl FnMut(usize, Item) -> Option<usize> + 'a { |
111 |
| - move |more, x| { |
112 |
| - action(x); |
113 |
| - more.checked_sub(1) |
114 |
| - } |
115 |
| - } |
| 104 | + fn fold<B, F>(self, init: B, f: F) -> B |
| 105 | + where |
| 106 | + Self: Sized, |
| 107 | + F: FnMut(B, Self::Item) -> B, |
| 108 | + { |
| 109 | + Self::spec_fold(self, init, f) |
| 110 | + } |
116 | 111 |
|
117 |
| - let remaining = self.n; |
118 |
| - if remaining > 0 { |
119 |
| - self.iter.try_fold(remaining - 1, check(f)); |
120 |
| - } |
| 112 | + #[inline] |
| 113 | + fn for_each<F: FnMut(Self::Item)>(self, f: F) { |
| 114 | + Self::spec_for_each(self, f) |
121 | 115 | }
|
122 | 116 |
|
123 | 117 | #[inline]
|
@@ -249,3 +243,72 @@ impl<I> FusedIterator for Take<I> where I: FusedIterator {}
|
249 | 243 |
|
250 | 244 | #[unstable(feature = "trusted_len", issue = "37572")]
|
251 | 245 | unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
|
| 246 | + |
| 247 | +trait SpecTake: Iterator { |
| 248 | + fn spec_fold<B, F>(self, init: B, f: F) -> B |
| 249 | + where |
| 250 | + Self: Sized, |
| 251 | + F: FnMut(B, Self::Item) -> B; |
| 252 | + |
| 253 | + fn spec_for_each<F: FnMut(Self::Item)>(self, f: F); |
| 254 | +} |
| 255 | + |
| 256 | +impl<I: Iterator> SpecTake for Take<I> { |
| 257 | + #[inline] |
| 258 | + default fn spec_fold<B, F>(mut self, init: B, f: F) -> B |
| 259 | + where |
| 260 | + Self: Sized, |
| 261 | + F: FnMut(B, Self::Item) -> B, |
| 262 | + { |
| 263 | + use crate::ops::NeverShortCircuit; |
| 264 | + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 |
| 265 | + } |
| 266 | + |
| 267 | + #[inline] |
| 268 | + default fn spec_for_each<F: FnMut(Self::Item)>(mut self, f: F) { |
| 269 | + // The default implementation would use a unit accumulator, so we can |
| 270 | + // avoid a stateful closure by folding over the remaining number |
| 271 | + // of items we wish to return instead. |
| 272 | + fn check<'a, Item>( |
| 273 | + mut action: impl FnMut(Item) + 'a, |
| 274 | + ) -> impl FnMut(usize, Item) -> Option<usize> + 'a { |
| 275 | + move |more, x| { |
| 276 | + action(x); |
| 277 | + more.checked_sub(1) |
| 278 | + } |
| 279 | + } |
| 280 | + |
| 281 | + let remaining = self.n; |
| 282 | + if remaining > 0 { |
| 283 | + self.iter.try_fold(remaining - 1, check(f)); |
| 284 | + } |
| 285 | + } |
| 286 | +} |
| 287 | + |
| 288 | +impl<I: Iterator + TrustedRandomAccess> SpecTake for Take<I> { |
| 289 | + #[inline] |
| 290 | + fn spec_fold<B, F>(mut self, init: B, mut f: F) -> B |
| 291 | + where |
| 292 | + Self: Sized, |
| 293 | + F: FnMut(B, Self::Item) -> B, |
| 294 | + { |
| 295 | + let mut acc = init; |
| 296 | + let end = self.n.min(self.iter.size()); |
| 297 | + for i in 0..end { |
| 298 | + // SAFETY: i < end <= self.iter.size() and we discard the iterator at the end |
| 299 | + let val = unsafe { self.iter.__iterator_get_unchecked(i) }; |
| 300 | + acc = f(acc, val); |
| 301 | + } |
| 302 | + acc |
| 303 | + } |
| 304 | + |
| 305 | + #[inline] |
| 306 | + fn spec_for_each<F: FnMut(Self::Item)>(mut self, mut f: F) { |
| 307 | + let end = self.n.min(self.iter.size()); |
| 308 | + for i in 0..end { |
| 309 | + // SAFETY: i < end <= self.iter.size() and we discard the iterator at the end |
| 310 | + let val = unsafe { self.iter.__iterator_get_unchecked(i) }; |
| 311 | + f(val); |
| 312 | + } |
| 313 | + } |
| 314 | +} |
0 commit comments