@@ -244,15 +244,32 @@ pub trait TupleCollect: Sized {
244244 fn left_shift_push ( & mut self , item : Self :: Item ) ;
245245}
246246
247+ macro_rules! count_ident{
248+ ( ) => { 0 } ;
249+ ( $i0: ident, $( $i: ident, ) * ) => { 1 + count_ident!( $( $i, ) * ) } ;
250+ }
251+ macro_rules! ignore_ident{
252+ ( $id: ident, $( $t: tt) * ) => { $( $t) * } ;
253+ }
254+ macro_rules! rev_for_each_ident{
255+ ( $m: ident, ) => { } ;
256+ ( $m: ident, $i0: ident, $( $i: ident, ) * ) => {
257+ rev_for_each_ident!( $m, $( $i, ) * ) ;
258+ $m!( $i0) ;
259+ } ;
260+ }
261+
247262macro_rules! impl_tuple_collect {
248- ( $N: expr; $A: ident ; $( $X: ident) ,* ; $( $Y: ident) ,* ; $( $Y_rev: ident) ,* ) => (
249- impl <$A> TupleCollect for ( $( $X) ,* , ) {
250- type Item = $A;
251- type Buffer = [ Option <$A>; $N - 1 ] ;
263+ ( $dummy: ident, ) => { } ; // stop
264+ ( $dummy: ident, $( $Y: ident, ) * ) => (
265+ impl_tuple_collect!( $( $Y, ) * ) ;
266+ impl <A > TupleCollect for ( $( ignore_ident!( $Y, A ) , ) * ) {
267+ type Item = A ;
268+ type Buffer = [ Option <A >; count_ident!( $( $Y, ) * ) - 1 ] ;
252269
253270 #[ allow( unused_assignments, unused_mut) ]
254271 fn collect_from_iter<I >( iter: I , buf: & mut Self :: Buffer ) -> Option <Self >
255- where I : IntoIterator <Item = $ A>
272+ where I : IntoIterator <Item = A >
256273 {
257274 let mut iter = iter. into_iter( ) ;
258275 $(
@@ -281,7 +298,7 @@ macro_rules! impl_tuple_collect {
281298 }
282299
283300 fn collect_from_iter_no_buf<I >( iter: I ) -> Option <Self >
284- where I : IntoIterator <Item = $ A>
301+ where I : IntoIterator <Item = A >
285302 {
286303 let mut iter = iter. into_iter( ) ;
287304
@@ -291,44 +308,20 @@ macro_rules! impl_tuple_collect {
291308 }
292309
293310 fn num_items( ) -> usize {
294- $N
311+ count_ident! ( $ ( $Y , ) * )
295312 }
296313
297- fn left_shift_push( & mut self , item: $ A) {
314+ fn left_shift_push( & mut self , mut item: A ) {
298315 use std:: mem:: replace;
299316
300317 let & mut ( $( ref mut $Y) ,* , ) = self ;
301- $(
302- let item = replace( $Y_rev, item) ;
303- ) *
318+ macro_rules! replace_item{ ( $i: ident) => {
319+ item = replace( $i, item) ;
320+ } } ;
321+ rev_for_each_ident!( replace_item, $( $Y, ) * ) ;
304322 drop( item) ;
305323 }
306324 }
307325 )
308326}
309-
310- // This snippet generates the twelve `impl_tuple_collect!` invocations:
311- // use core::iter;
312- // use itertools::Itertools;
313- //
314- // for i in 1..=12 {
315- // println!("impl_tuple_collect!({arity}; A; {ty}; {idents}; {rev_idents});",
316- // arity=i,
317- // ty=iter::repeat("A").take(i).join(", "),
318- // idents=('a'..='z').take(i).join(", "),
319- // rev_idents=('a'..='z').take(i).collect_vec().into_iter().rev().join(", ")
320- // );
321- // }
322- // It could probably be replaced by a bit more macro cleverness.
323- impl_tuple_collect ! ( 1 ; A ; A ; a; a) ;
324- impl_tuple_collect ! ( 2 ; A ; A , A ; a, b; b, a) ;
325- impl_tuple_collect ! ( 3 ; A ; A , A , A ; a, b, c; c, b, a) ;
326- impl_tuple_collect ! ( 4 ; A ; A , A , A , A ; a, b, c, d; d, c, b, a) ;
327- impl_tuple_collect ! ( 5 ; A ; A , A , A , A , A ; a, b, c, d, e; e, d, c, b, a) ;
328- impl_tuple_collect ! ( 6 ; A ; A , A , A , A , A , A ; a, b, c, d, e, f; f, e, d, c, b, a) ;
329- impl_tuple_collect ! ( 7 ; A ; A , A , A , A , A , A , A ; a, b, c, d, e, f, g; g, f, e, d, c, b, a) ;
330- impl_tuple_collect ! ( 8 ; A ; A , A , A , A , A , A , A , A ; a, b, c, d, e, f, g, h; h, g, f, e, d, c, b, a) ;
331- impl_tuple_collect ! ( 9 ; A ; A , A , A , A , A , A , A , A , A ; a, b, c, d, e, f, g, h, i; i, h, g, f, e, d, c, b, a) ;
332- impl_tuple_collect ! ( 10 ; A ; A , A , A , A , A , A , A , A , A , A ; a, b, c, d, e, f, g, h, i, j; j, i, h, g, f, e, d, c, b, a) ;
333- impl_tuple_collect ! ( 11 ; A ; A , A , A , A , A , A , A , A , A , A , A ; a, b, c, d, e, f, g, h, i, j, k; k, j, i, h, g, f, e, d, c, b, a) ;
334- impl_tuple_collect ! ( 12 ; A ; A , A , A , A , A , A , A , A , A , A , A , A ; a, b, c, d, e, f, g, h, i, j, k, l; l, k, j, i, h, g, f, e, d, c, b, a) ;
327+ impl_tuple_collect ! ( dummy, a, b, c, d, e, f, g, h, i, j, k, l, ) ;
0 commit comments