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 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 {} } 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) -> ::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; }); 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; });