pub trait TypedTuple<const INDEX: usize, T> {
fn get(&self) -> &T;
fn get_mut(&mut self) -> &mut T;
fn map<FN: FnOnce(T) -> T>(&mut self, f: FN)
where
T: Default;
}
macro_rules! impl_typed_tuple {
(( $($generics:tt ),* ), [ $( $( $idx_tail:tt ),+ )? ], []) => {};
(( $($generics:tt ),* ), [$idx_head:tt $(, $idx_tail:tt )* ], [ $gen_head:tt $(, $gen_tail:tt )* ]) => {
impl< $( $generics ),+ > TypedTuple<$idx_head, $gen_head> for ( $( $generics ),+ ) {
fn get(&self) -> &$gen_head {
&self.$idx_head
}
fn get_mut(&mut self) -> &mut $gen_head {
&mut self.$idx_head
}
fn map<FN: FnOnce($gen_head) -> $gen_head>(&mut self, f: FN) where $gen_head: Default {
self.$idx_head = f(std::mem::take(&mut self.$idx_head));
}
}
impl_typed_tuple!(($( $generics ),* ), [ $( $idx_tail ),* ], [ $( $gen_tail ),* ]);
};
(( $($generics:tt),* )) => {
impl_typed_tuple!(
( $( $generics ),* ),
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[ $( $generics ),* ]);
}
}
impl_typed_tuple!((A, B));
impl_typed_tuple!((A, B, C));
impl_typed_tuple!((A, B, C, D));
impl_typed_tuple!((A, B, C, D, E));
impl_typed_tuple!((A, B, C, D, E, F));
impl_typed_tuple!((A, B, C, D, E, F, G));
impl_typed_tuple!((A, B, C, D, E, F, G, H));
impl_typed_tuple!((A, B, C, D, E, F, G, H, I));
impl_typed_tuple!((A, B, C, D, E, F, G, H, I, K));
impl_typed_tuple!((A, B, C, D, E, F, G, H, I, K, J));
impl_typed_tuple!((A, B, C, D, E, F, G, H, I, K, J, L));