94
94
ZipImpl :: nth ( self , n)
95
95
}
96
96
97
+ #[ inline]
98
+ fn fold < Acc , F > ( self , init : Acc , f : F ) -> Acc
99
+ where
100
+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
101
+ {
102
+ ZipImpl :: fold ( self , init, f)
103
+ }
104
+
97
105
#[ inline]
98
106
unsafe fn __iterator_get_unchecked ( & mut self , idx : usize ) -> Self :: Item
99
107
where
@@ -129,6 +137,9 @@ trait ZipImpl<A, B> {
129
137
where
130
138
A : DoubleEndedIterator + ExactSizeIterator ,
131
139
B : DoubleEndedIterator + ExactSizeIterator ;
140
+ fn fold < Acc , F > ( self , init : Acc , f : F ) -> Acc
141
+ where
142
+ F : FnMut ( Acc , Self :: Item ) -> Acc ;
132
143
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
133
144
unsafe fn get_unchecked ( & mut self , idx : usize ) -> <Self as Iterator >:: Item
134
145
where
@@ -228,6 +239,14 @@ where
228
239
{
229
240
unreachable ! ( "Always specialized" ) ;
230
241
}
242
+
243
+ #[ inline]
244
+ default fn fold < Acc , F > ( self , init : Acc , f : F ) -> Acc
245
+ where
246
+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
247
+ {
248
+ SpecFold :: spec_fold ( self , init, f)
249
+ }
231
250
}
232
251
233
252
#[ doc( hidden) ]
@@ -251,6 +270,24 @@ where
251
270
// `Iterator::__iterator_get_unchecked`.
252
271
unsafe { ( self . a . __iterator_get_unchecked ( idx) , self . b . __iterator_get_unchecked ( idx) ) }
253
272
}
273
+
274
+ #[ inline]
275
+ fn fold < Acc , F > ( mut self , init : Acc , mut f : F ) -> Acc
276
+ where
277
+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
278
+ {
279
+ let mut accum = init;
280
+ let len = ZipImpl :: size_hint ( & self ) . 0 ;
281
+ for i in 0 ..len {
282
+ // SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to
283
+ // calculate the length and then use that to do unchecked iteration.
284
+ // fold consumes the iterator so we don't need to fixup any state.
285
+ unsafe {
286
+ accum = f ( accum, self . get_unchecked ( i) ) ;
287
+ }
288
+ }
289
+ accum
290
+ }
254
291
}
255
292
256
293
#[ doc( hidden) ]
@@ -590,3 +627,56 @@ unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccess f
590
627
unsafe { self . __iterator_get_unchecked ( index) }
591
628
}
592
629
}
630
+
631
+ trait SpecFold : Iterator {
632
+ fn spec_fold < B , F > ( self , init : B , f : F ) -> B
633
+ where
634
+ Self : Sized ,
635
+ F : FnMut ( B , Self :: Item ) -> B ;
636
+ }
637
+
638
+ impl < A : Iterator , B : Iterator > SpecFold for Zip < A , B > {
639
+ // Adapted from default impl from the Iterator trait
640
+ #[ inline]
641
+ default fn spec_fold < Acc , F > ( mut self , init : Acc , mut f : F ) -> Acc
642
+ where
643
+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
644
+ {
645
+ let mut accum = init;
646
+ while let Some ( x) = ZipImpl :: next ( & mut self ) {
647
+ accum = f ( accum, x) ;
648
+ }
649
+ accum
650
+ }
651
+ }
652
+
653
+ impl < A : TrustedLen , B : TrustedLen > SpecFold for Zip < A , B > {
654
+ #[ inline]
655
+ fn spec_fold < Acc , F > ( mut self , init : Acc , mut f : F ) -> Acc
656
+ where
657
+ F : FnMut ( Acc , Self :: Item ) -> Acc ,
658
+ {
659
+ let mut accum = init;
660
+ loop {
661
+ let ( upper, more) = if let Some ( upper) = ZipImpl :: size_hint ( & self ) . 1 {
662
+ ( upper, false )
663
+ } else {
664
+ // Per TrustedLen contract a None upper bound means more than usize::MAX items
665
+ ( usize:: MAX , true )
666
+ } ;
667
+
668
+ for _ in 0 ..upper {
669
+ let pair =
670
+ // SAFETY: TrustedLen guarantees that at least `upper` many items are available
671
+ // therefore we know they can't be None
672
+ unsafe { ( self . a . next ( ) . unwrap_unchecked ( ) , self . b . next ( ) . unwrap_unchecked ( ) ) } ;
673
+ accum = f ( accum, pair) ;
674
+ }
675
+
676
+ if !more {
677
+ break ;
678
+ }
679
+ }
680
+ accum
681
+ }
682
+ }
0 commit comments