11use alloc:: boxed:: Box ;
2- use alloc :: vec :: Vec ;
2+ use core :: array ;
33use std:: fmt;
44use std:: iter:: FusedIterator ;
55
66use super :: lazy_buffer:: LazyBuffer ;
77use crate :: adaptors:: checked_binomial;
8-
8+ use crate :: combinations :: PoolIndex ;
99/// An iterator to iterate through all the `n`-length combinations in an iterator, with replacement.
1010///
1111/// See [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement)
1212/// for more information.
1313#[ derive( Clone ) ]
1414#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
15- pub struct CombinationsWithReplacement < I >
15+ pub struct CombinationsWithReplacementGeneric < I , Idx >
1616where
1717 I : Iterator ,
1818 I :: Item : Clone ,
1919{
20- indices : Box < [ usize ] > ,
20+ indices : Idx ,
2121 pool : LazyBuffer < I > ,
2222 first : bool ,
2323}
2424
25- impl < I > fmt:: Debug for CombinationsWithReplacement < I >
25+ /// Iterator for `Box<[I]>` valued combinations_with_replacement returned by [`.combinations_with_replacement()`](crate::Itertools::combinations_with_replacement)
26+ pub type CombinationsWithReplacement < I > = CombinationsWithReplacementGeneric < I , Box < [ usize ] > > ;
27+ impl < I , Idx > fmt:: Debug for CombinationsWithReplacementGeneric < I , Idx >
2628where
2729 I : Iterator + fmt:: Debug ,
2830 I :: Item : fmt:: Debug + Clone ,
31+ Idx : fmt:: Debug ,
2932{
30- debug_fmt_fields ! ( CombinationsWithReplacement , indices, pool, first) ;
33+ debug_fmt_fields ! ( CombinationsWithReplacementGeneric , indices, pool, first) ;
3134}
3235
3336/// Create a new `CombinationsWithReplacement` from a clonable iterator.
@@ -37,16 +40,11 @@ where
3740 I :: Item : Clone ,
3841{
3942 let indices = alloc:: vec![ 0 ; k] . into_boxed_slice ( ) ;
40- let pool: LazyBuffer < I > = LazyBuffer :: new ( iter) ;
4143
42- CombinationsWithReplacement {
43- indices,
44- pool,
45- first : true ,
46- }
44+ CombinationsWithReplacementGeneric :: new ( iter, indices)
4745}
4846
49- impl < I > CombinationsWithReplacement < I >
47+ impl < I : Iterator , Idx : PoolIndex < I :: Item > > CombinationsWithReplacementGeneric < I , Idx >
5048where
5149 I : Iterator ,
5250 I :: Item : Clone ,
6260
6361 // Work out where we need to update our indices
6462 let mut increment = None ;
65- for ( i, indices_int) in self . indices . iter ( ) . enumerate ( ) . rev ( ) {
63+ let indices: & mut [ usize ] = self . indices . borrow_mut ( ) ;
64+ for ( i, indices_int) in indices. iter ( ) . enumerate ( ) . rev ( ) {
6665 if * indices_int < self . pool . len ( ) - 1 {
6766 increment = Some ( ( i, indices_int + 1 ) ) ;
6867 break ;
@@ -73,39 +72,52 @@ where
7372 Some ( ( increment_from, increment_value) ) => {
7473 // We need to update the rightmost non-max value
7574 // and all those to the right
76- self . indices [ increment_from..] . fill ( increment_value) ;
75+ indices[ increment_from..] . fill ( increment_value) ;
7776 false
7877 }
7978 // Otherwise, we're done
8079 None => true ,
8180 }
8281 }
82+ /// Constructor with arguments the inner iterator and the initial state for the indices.
83+ fn new ( iter : I , indices : Idx ) -> Self {
84+ Self {
85+ indices,
86+ pool : LazyBuffer :: new ( iter) ,
87+ first : true ,
88+ }
89+ }
8390}
8491
85- impl < I > Iterator for CombinationsWithReplacement < I >
92+ impl < I , Idx > Iterator for CombinationsWithReplacementGeneric < I , Idx >
8693where
8794 I : Iterator ,
8895 I :: Item : Clone ,
96+ Idx : PoolIndex < I :: Item > ,
8997{
90- type Item = Vec < I :: Item > ;
98+ type Item = Idx :: Item ;
9199
92100 fn next ( & mut self ) -> Option < Self :: Item > {
93101 if self . first {
94102 // In empty edge cases, stop iterating immediately
95- if !( self . indices . is_empty ( ) || self . pool . get_next ( ) ) {
103+ if !( core:: borrow:: Borrow :: < [ usize ] > :: borrow ( & self . indices ) . is_empty ( )
104+ || self . pool . get_next ( ) )
105+ {
96106 return None ;
97107 }
98108 self . first = false ;
99109 } else if self . increment_indices ( ) {
100110 return None ;
101111 }
102- Some ( self . pool . get_at ( & self . indices ) )
112+ Some ( self . indices . extract_item ( & self . pool ) )
103113 }
104114
105115 fn nth ( & mut self , n : usize ) -> Option < Self :: Item > {
106116 if self . first {
107117 // In empty edge cases, stop iterating immediately
108- if !( self . indices . is_empty ( ) || self . pool . get_next ( ) ) {
118+ if !( core:: borrow:: Borrow :: < [ usize ] > :: borrow ( & self . indices ) . is_empty ( )
119+ || self . pool . get_next ( ) )
120+ {
109121 return None ;
110122 }
111123 self . first = false ;
@@ -117,13 +129,13 @@ where
117129 return None ;
118130 }
119131 }
120- Some ( self . pool . get_at ( & self . indices ) )
132+ Some ( self . indices . extract_item ( & self . pool ) )
121133 }
122134
123135 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
124136 let ( mut low, mut upp) = self . pool . size_hint ( ) ;
125- low = remaining_for ( low, self . first , & self . indices ) . unwrap_or ( usize:: MAX ) ;
126- upp = upp. and_then ( |upp| remaining_for ( upp, self . first , & self . indices ) ) ;
137+ low = remaining_for ( low, self . first , self . indices . borrow ( ) ) . unwrap_or ( usize:: MAX ) ;
138+ upp = upp. and_then ( |upp| remaining_for ( upp, self . first , self . indices . borrow ( ) ) ) ;
127139 ( low, upp)
128140 }
129141
@@ -134,14 +146,15 @@ where
134146 first,
135147 } = self ;
136148 let n = pool. count ( ) ;
137- remaining_for ( n, first, & indices) . unwrap ( )
149+ remaining_for ( n, first, indices. borrow ( ) ) . unwrap ( )
138150 }
139151}
140152
141- impl < I > FusedIterator for CombinationsWithReplacement < I >
153+ impl < I , Idx > FusedIterator for CombinationsWithReplacementGeneric < I , Idx >
142154where
143155 I : Iterator ,
144156 I :: Item : Clone ,
157+ Idx : PoolIndex < I :: Item > ,
145158{
146159}
147160
0 commit comments