use varihappy_macros::{
reverse_expr_type, reverse_tuple_type, tuple_expr_len_rest, tuple_expr_mut, tuple_expr_ref,
tuple_type_len, tuple_type_len_rest,
};
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;
}
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<A> 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<A> Tuple1 for (A,) {
type Item0 = A;
type Rest = ();
fn into_0(self) -> Self::Item0 {
self.0
}
fn split_into(self) -> (Self::Item0, <Self as Tuple1>::Rest) {
(self.0, ())
}
fn into_rest(self) -> Self::Rest {}
}
macro_rules! impl_tuple {
($length: expr; $($letter: ident),*) => {
impl<$($letter),*> Tuple for tuple_type_len!($length) {
type AsRef<'a> = ($(&'a $letter,)*) where Self: 'a;
type AsMut<'a> = ($(&'a mut $letter,)*) where Self: 'a;
type Reversed = reverse_tuple_type!($length);
fn as_ref(&self) -> Self::AsRef<'_> {
tuple_expr_ref!($length)
}
fn as_mut(&mut self) -> Self::AsMut<'_> {
tuple_expr_mut!($length)
}
fn rev(self) -> Self::Reversed {
reverse_expr_type!($length)
}
}
impl<$($letter),*> Tuple1 for tuple_type_len!($length) {
type Item0 = A;
type Rest = tuple_type_len_rest!($length);
fn into_0(self) -> Self::Item0 {
self.0
}
fn split_into(self) -> (Self::Item0, Self::Rest) {
(self.0, tuple_expr_len_rest!($length))
}
fn into_rest(self) -> Self::Rest {
tuple_expr_len_rest!($length)
}
}
};
}
impl_tuple!(2; A, B);
impl_tuple!(3; A, B, C);
impl_tuple!(4; A, B, C, D);
impl_tuple!(5; A, B, C, D, E);
impl_tuple!(6; A, B, C, D, E, F);
impl_tuple!(7; A, B, C, D, E, F, G);
impl_tuple!(8; A, B, C, D, E, F, G, H);
impl_tuple!(9; A, B, C, D, E, F, G, H, I);
impl_tuple!(10; A, B, C, D, E, F, G, H, I, J);
impl_tuple!(11; A, B, C, D, E, F, G, H, I, J, K);
impl_tuple!(12; A, B, C, D, E, F, G, H, I, J, K, L);
impl_tuple!(13; A, B, C, D, E, F, G, H, I, J, K, L, M);
impl_tuple!(14; A, B, C, D, E, F, G, H, I, J, K, L, M, N);
impl_tuple!(15; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
impl_tuple!(16; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
impl_tuple!(17; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
impl_tuple!(18; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
impl_tuple!(19; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
impl_tuple!(20; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
impl_tuple!(21; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
impl_tuple!(22; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
impl_tuple!(23; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
impl_tuple!(24; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
impl_tuple!(25; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
impl_tuple!(26; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
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()
}
}
};
}
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; });
tuple_trait!(trait Tuple6 for Tuple5 { type Item5; fn into_5; });
tuple_trait!(trait Tuple7 for Tuple6 { type Item6; fn into_6; });
tuple_trait!(trait Tuple8 for Tuple7 { type Item7; fn into_7; });
tuple_trait!(trait Tuple9 for Tuple8 { type Item8; fn into_8; });
tuple_trait!(trait Tuple10 for Tuple9 { type Item9; fn into_9; });
tuple_trait!(trait Tuple11 for Tuple10 { type Item10; fn into_10; });
tuple_trait!(trait Tuple12 for Tuple11 { type Item11; fn into_11; });
tuple_trait!(trait Tuple13 for Tuple12 { type Item12; fn into_12; });
tuple_trait!(trait Tuple14 for Tuple13 { type Item13; fn into_13; });
tuple_trait!(trait Tuple15 for Tuple14 { type Item14; fn into_14; });
tuple_trait!(trait Tuple16 for Tuple15 { type Item15; fn into_15; });
tuple_trait!(trait Tuple17 for Tuple16 { type Item16; fn into_16; });
tuple_trait!(trait Tuple18 for Tuple17 { type Item17; fn into_17; });
tuple_trait!(trait Tuple19 for Tuple18 { type Item18; fn into_18; });
tuple_trait!(trait Tuple20 for Tuple19 { type Item19; fn into_19; });
tuple_trait!(trait Tuple21 for Tuple20 { type Item20; fn into_20; });
tuple_trait!(trait Tuple22 for Tuple21 { type Item21; fn into_21; });
tuple_trait!(trait Tuple23 for Tuple22 { type Item22; fn into_22; });
tuple_trait!(trait Tuple24 for Tuple23 { type Item23; fn into_23; });
tuple_trait!(trait Tuple25 for Tuple24 { type Item24; fn into_24; });
tuple_trait!(trait Tuple26 for Tuple25 { type Item25; fn into_25; });
|