1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#![no_std]
#![feature(trait_alias)]
#![feature(generic_const_exprs)]
#![feature(const_trait_impl)]
#![feature(const_precise_live_drops)]
//! This crate is an extension for the [tupleops](tupleops) crate,
//! which adds a trait for splitting tuples by index.
//!
//! Tuples which may be split at index MIDDLE have the trait [TupleSplit](crate::TupleSplit)<MIDDLE>,
//! which, when split, returns ([TupleSplit::Left](TupleSplit::Left), [TupleSplit::Right](TupleSplit::Right)).
//!
//! Type alias [Left](Left) and [Right](Right) equal [TupleSplit::Left](TupleSplit::Left) and [TupleSplit::Right](TupleSplit::Right) respectively.
//! fpr any tuple which implements [TupleSplit](crate::TupleSplit) at the given MIDDLE.
//!
//! The trait alias [SplitLeftInto](SplitLeftInto) is implemented for any tuple which may be split where [TupleSplit::Left](TupleSplit::Left) = L.
//!
//! The trait alias [SplitRightInto](SplitRightInto) is implemented for any tuple which may be split where [TupleSplit::Right](TupleSplit::Right) = R.
//!
//! The trait alias [SplitInto](SplitInto) is implemented for any tuple which may be split where [TupleSplit::Left](TupleSplit::Left) = L and [TupleSplit::Right](TupleSplit::Right) = R.
//!
//! ```rust
//! use tupleops::concat_tuples;
//! use tuple_split::*;
//!
//! let t: (u8, f32, &str) = (1, 1.0, "test");
//!
//! let (l, r): ((u8, f32), (&str,)) = TupleSplit::<2>::split_tuple(t);
//!
//! assert_eq!(t, concat_tuples(l, r));
//!
//! let (l, r): ((u8, f32), (&str,)) = split_tuple::<2, _>(t);
//!
//! assert_eq!(t, concat_tuples(l, r));
//! ```
use blk_count_macro::count;
use tupleops::{TupleLength, Tuple};
/// Type alias [Left](Left) equals [TupleSplit::Left](TupleSplit::Left)
/// for any tuple which implements [TupleSplit](crate::TupleSplit) at the given MIDDLE.
pub type Left<T, const MIDDLE: usize> = <T as TupleSplit<MIDDLE>>::Left;
/// Type alias [Right](Right) equals [TupleSplit::Right](TupleSplit::Right)
/// for any tuple which implements [TupleSplit](crate::TupleSplit) at the given MIDDLE.
pub type Right<T, const MIDDLE: usize> = <T as TupleSplit<MIDDLE>>::Right;
/// The trait alias [SplitLeftInto](SplitLeftInto) is implemented for any tuple which may be split where [TupleSplit::Left](TupleSplit::Left) = L.
pub trait SplitLeftInto<L> = TupleSplit<{<L as TupleLength>::LENGTH}, Left = L>
where L: TupleLength, [(); <L as TupleLength>::LENGTH]:;
/// The trait alias [SplitRightInto](SplitRightInto) is implemented for any tuple which may be split where [TupleSplit::Right](TupleSplit::Right) = R.
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]:;
/// The trait alias [SplitInto](SplitInto) is implemented for any tuple which may be split where [TupleSplit::Left](TupleSplit::Left) = L and [TupleSplit::Right](TupleSplit::Right) = R.
pub trait SplitInto<L, R> = TupleSplit<{<L as TupleLength>::LENGTH}, Left = L, Right = R>
where L: TupleLength, [(); <L as TupleLength>::LENGTH]:;
/// Tuples which may be split at index MIDDLE have the trait [TupleSplit](crate::TupleSplit)<MIDDLE>,
/// which, when split, returns ([TupleSplit::Left](TupleSplit::Left), [TupleSplit::Right](TupleSplit::Right)).
///
/// ```rust
/// use tupleops::concat_tuples;
/// use tuple_split::*;
///
/// let t: (u8, f32, &str) = (1, 1.0, "test");
/// let (l, r): ((u8, f32), (&str,)) = TupleSplit::<2>::split_tuple(t);
///
/// assert_eq!(t, concat_tuples(l, r));
/// ```
#[const_trait]
pub trait TupleSplit<const MIDDLE: usize>: Tuple
{
type Left;
type Right;
fn split_tuple(self) -> (Self::Left, Self::Right);
}
/// Splits tuple at a given index.
///
/// Index is specified as const generic MIDDLE.
///
/// Tuple must be of trait [TupleSplit](crate::TupleSplit)<MIDDLE>.
///
/// Returns ([TupleSplit::Left](TupleSplit::Left), [TupleSplit::Right](TupleSplit::Right)) for the given Tuple and MIDDLE.
///
/// ```rust
/// use tupleops::concat_tuples;
/// use tuple_split::*;
///
/// let t: (u8, f32, &str) = (1, 1.0, "test");
/// let (l, r): ((u8, f32), (&str,)) = split_tuple::<2, _>(t);
///
/// assert_eq!(t, concat_tuples(l, r));
/// ```
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)
}