diff options
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 137 |
1 files changed, 75 insertions, 62 deletions
@@ -22,12 +22,45 @@ pub trait Tuple1: Tuple { fn into_rest(self) -> Self::Rest; } -pub trait Tuple2: Tuple1 { - type Item1; - type Rest: Tuple; - - fn into_1(self) -> Self::Item1; - fn into_rest(self) -> <Self as Tuple2>::Rest; +macro_rules! impl_tuple { + ( + A, $($letter: ident),* => $($letter_reverse: ident),*; + 0, $($number: tt),* => $($number_reverse: tt),* + ) => { + impl<A,$($letter),*> 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<A, $($letter),*> 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 () { @@ -62,38 +95,11 @@ impl<A> Tuple for (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.0,) - } -} - -impl<A, B> Tuple for (A, B) { - type AsRef<'a> - = (&'a A, &'a B) - where - Self: 'a; - type AsMut<'a> - = (&'a mut A, &'a mut B) - where - Self: 'a; - - type Reversed = (B, A); - - fn as_ref(&self) -> Self::AsRef<'_> { - (&self.0, &self.1) - } - - fn as_mut(&mut self) -> Self::AsMut<'_> { - (&mut self.0, &mut self.1) - } - fn rev(self) -> Self::Reversed { - (self.1, self.0) + self } } @@ -112,33 +118,40 @@ impl<A> Tuple1 for (A,) { fn into_rest(self) -> Self::Rest {} } -impl<A, B> Tuple1 for (A, B) { - type Item0 = A; - - type Rest = (B,); - - fn into_0(self) -> Self::Item0 { - self.0 - } - - fn split_into(self) -> (Self::Item0, <Self as Tuple1>::Rest) { - (self.0, (self.1,)) - } - - fn into_rest(self) -> Self::Rest { - (self.1,) - } +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) -> <Self as $trait_name>::Rest; + } + + impl<R: Tuple1, T: $trait_minus1<Rest = R>> $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) -> <Self as $trait_name>::Rest { + $trait_minus1::into_rest(self).into_rest() + } + } + }; } -impl<R: Tuple1, T: Tuple1<Rest = R>> Tuple2 for T { - type Item1 = R::Item0; - type Rest = R::Rest; - - fn into_1(self) -> Self::Item1 { - self.into_rest().into_0() - } - - fn into_rest(self) -> <Self as Tuple2>::Rest { - self.into_rest().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; }); |
