#![no_std]
#![feature(trait_alias)]
#![feature(generic_const_exprs)]
#![feature(const_trait_impl)]
#![feature(const_precise_live_drops)]
use blk_count_macro::count;
use tupleops::{TupleLength, Tuple};
pub type Left<T, const MIDDLE: usize> = <T as TupleSplit<MIDDLE>>::Left;
pub type Right<T, const MIDDLE: usize> = <T as TupleSplit<MIDDLE>>::Right;
pub trait SplitLeftInto<L> = TupleSplit<{<L as TupleLength>::LENGTH}, Left = L>
where L: TupleLength, [(); <L as TupleLength>::LENGTH]:;
pub trait SplitRightInto<R> = TupleSplit<{<Self as TupleLength>::LENGTH - <R as TupleLength>::LENGTH}, Right = R> + TupleLength
where R: TupleLength, [(); <Self as TupleLength>::LENGTH - <R as TupleLength>::LENGTH]:;
pub trait SplitInto<L, R> = TupleSplit<{<L as TupleLength>::LENGTH}, Left = L, Right = R>
where L: TupleLength, [(); <L as TupleLength>::LENGTH]:;
#[const_trait]
pub trait TupleSplit<const MIDDLE: usize>: Tuple
{
type Left;
type Right;
fn split_tuple(self) -> (Self::Left, Self::Right);
}
pub const fn split_tuple<const MIDDLE: usize, T>(tuple: T) -> (T::Left, T::Right)
where
T: ~const TupleSplit<MIDDLE>
{
tuple.split_tuple()
}
macro_rules! impl_split_single {
(( $($types1:ident),* ), ( $($types2:ident),* )) => {
impl<$($types1,)* $($types2,)*> const TupleSplit<{count!($($types1),*)}> for ($($types1,)* $($types2,)*)
{
type Left = ($($types1,)*);
type Right = ($($types2,)*);
fn split_tuple(self) -> (Self::Left, Self::Right)
{
let ($($types1,)* $($types2,)*) = self;
(($($types1,)*), ($($types2,)*))
}
}
};
}
macro_rules! impl_split_combinations {
( (), ( $($types2:ident),* ) ) => {
impl_split_single!{(), ($($types2),*)}
};
(($t0:ident $(,$types1:ident)* ), ( $($types2:ident),* )) => {
impl_split_single!{($t0 $(,$types1)*), ($($types2),*)}
impl_split_combinations!{($($types1),*), ($t0 $(,$types2)*)}
};
(($($types:ident),*)) => {
impl_split_combinations!{($($types),*), ()}
}
}
macro_rules! impl_split_all {
(()) => {
impl_split_combinations!{()}
};
(($t0:ident $(,$types:ident)*)) => {
impl_split_combinations!{($t0 $(,$types)*)}
impl_split_all!{($($types),*)}
}
}
impl_split_all!{
(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16)
}