summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs137
1 files changed, 75 insertions, 62 deletions
diff --git a/src/lib.rs b/src/lib.rs
index a7146b8..90bec23 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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; });