pub trait Tuple { type AsRef<'a>: Tuple where Self: 'a; type AsMut<'a>: Tuple where Self: 'a; type Reversed: Tuple; fn as_ref(&self) -> Self::AsRef<'_>; fn as_mut(&mut self) -> Self::AsMut<'_>; fn rev(self) -> Self::Reversed; } pub trait Tuple1: Tuple { type Item0; type Rest: Tuple; fn into_0(self) -> Self::Item0; fn split_into(self) -> (Self::Item0, Self::Rest); fn into_rest(self) -> Self::Rest; } macro_rules! impl_tuple { ( A, $($letter: ident),* => $($letter_reverse: ident),*; 0, $($number: tt),* => $($number_reverse: tt),* ) => { impl Tuple for (A,$($letter,)*) { type AsRef<'a> = (&'a A,$(&'a $letter,)*) where Self: 'a; type AsMut<'a> = (&'a mut A,$(&'a mut $letter,)*) where Self: 'a; type Reversed = ($($letter_reverse,)*); fn as_ref(&self) -> Self::AsRef<'_> { (&self.0,$(&self.$number,)*) } fn as_mut(&mut self) -> Self::AsMut<'_> { (&mut self.0,$(&mut self.$number,)*) } fn rev(self) -> Self::Reversed { ($(self.$number_reverse,)*) } } impl Tuple1 for (A, $($letter,)*) { type Item0 = A; type Rest = ($($letter,)*); fn into_0(self) -> Self::Item0 { self.0 } fn split_into(self) -> (Self::Item0, Self::Rest) { (self.0, ($(self.$number,)*)) } fn into_rest(self) -> Self::Rest { ($(self.$number,)*) } } }; } impl Tuple for () { type AsRef<'a> = () where Self: 'a; type AsMut<'a> = () where Self: 'a; type Reversed = (); fn as_ref(&self) -> Self::AsRef<'_> {} fn as_mut(&mut self) -> Self::AsMut<'_> {} fn rev(self) -> Self::Reversed {} } impl Tuple for (A,) { type AsRef<'a> = (&'a A,) where Self: 'a; type AsMut<'a> = (&'a mut A,) where Self: 'a; type Reversed = (A,); fn as_ref(&self) -> Self::AsRef<'_> { (&self.0,) } fn as_mut(&mut self) -> Self::AsMut<'_> { (&mut self.0,) } fn rev(self) -> Self::Reversed { self } } impl Tuple1 for (A,) { type Item0 = A; type Rest = (); fn into_0(self) -> Self::Item0 { self.0 } fn split_into(self) -> (Self::Item0, ::Rest) { (self.0, ()) } fn into_rest(self) -> Self::Rest {} } impl_tuple!(A, B => B, A; 0, 1 => 1, 0); impl_tuple!(A, B, C => C, B, A; 0, 1, 2 => 2, 1, 0); impl_tuple!(A, B, C, D => D, C, B, A; 0, 1, 2, 3 => 3, 2, 1, 0); impl_tuple!(A, B, C, D, E => E, D, C, B, A; 0, 1, 2, 3, 4 => 4, 3, 2, 1, 0); macro_rules! tuple_trait { (trait $trait_name: ident for $trait_minus1: ident { type $item_name: ident; fn $item_getter: ident; }) => { pub trait $trait_name: $trait_minus1 { type $item_name; type Rest: Tuple; fn $item_getter(self) -> Self::$item_name; fn into_rest(self) -> ::Rest; } impl> $trait_name for T { type $item_name = R::Item0; type Rest = R::Rest; fn $item_getter(self) -> Self::$item_name { $trait_minus1::into_rest(self).into_0() } fn into_rest(self) -> ::Rest { $trait_minus1::into_rest(self).into_rest() } } }; } tuple_trait!(trait Tuple2 for Tuple1 { type Item1; fn into_1; }); tuple_trait!(trait Tuple3 for Tuple2 { type Item2; fn into_2; }); tuple_trait!(trait Tuple4 for Tuple3 { type Item3; fn into_3; }); tuple_trait!(trait Tuple5 for Tuple4 { type Item4; fn into_4; });