tuple_split/
lib.rs

1#![no_std]
2#![feature(trait_alias)]
3#![feature(generic_const_exprs)]
4#![feature(const_trait_impl)]
5#![feature(const_precise_live_drops)]
6#![feature(tuple_trait)]
7#![recursion_limit = "512"]
8
9//!
10//! This crate an extension for the [tupleops](tupleops) crate.
11//!
12//! [tupleops](tupleops) contains many useful features for manipulating tuples andusing tuples in generic code.
13//! However, it does not support any kind of splitting of tuples. This crate adds that feature.
14//!
15//! # Examples
16//!
17//! ```rust
18//! #![feature(generic_const_exprs)]
19//!
20//! let t = (32, 0.707, "test");
21//!
22//! // Splitting tuples by index
23//! let (l, r) = tuple_split::split_tuple_at::<0, _>(t);
24//! assert_eq!(t, tupleops::concat_tuples(l, r));
25//!
26//! let (l, r) = tuple_split::split_tuple_at::<1, _>(t);
27//! assert_eq!(t, tupleops::concat_tuples(l, r));
28//!
29//! let (l, r) = tuple_split::split_tuple_at::<2, _>(t);
30//! assert_eq!(t, tupleops::concat_tuples(l, r));
31//!
32//! let (l, r) = tuple_split::split_tuple_at::<3, _>(t);
33//! assert_eq!(t, tupleops::concat_tuples(l, r));
34//!
35//! // Splitting tuples given a left side
36//! let (l, r) = tuple_split::split_tuple_into_left::<(u8, f32), _>(t);
37//! assert_eq!(t, tupleops::concat_tuples(l, r));
38//!
39//! // Splitting tuples given a right side
40//! let (l, r) = tuple_split::split_tuple_into_right::<(&str,), _>(t);
41//! assert_eq!(t, tupleops::concat_tuples(l, r));
42//!
43//! // Splitting tuples given both sides
44//! let (l, r) = tuple_split::split_tuple_into::<(u8, f32), (&str,)>(t);
45//! assert_eq!(t, tupleops::concat_tuples(l, r));
46//! ```
47//!
48//! # Split by index
49//!
50//! Tuples can be split by a const-generic index. To use this feature, put `#![feature(generic_const_exprs)]` on the top of your `lib.rs` or `main.rs`.
51//!
52//! ## Example
53//!
54//! ```rust
55//! #![feature(generic_const_exprs)]
56//!
57//! let t = (1, 1.0, "test");
58//!
59//! let (l, r) = tuple_split::split_tuple_at::<2, _>(t);
60//!
61//! assert_eq!(t, tupleops::concat_tuples(l, r));
62//! ```
63//!
64//! # Split by type
65//!
66//! The type of tuple you want from the split operation can be used instead of an index. This does not require `#![feature(generic_const_exprs)]`. Either the left, right
67//! or both can be provided as a generic type.
68//!
69//! ## Examples
70//!
71//! ### Left
72//!
73//! ```rust
74//! let t = (1, 1.0, "test");
75//!
76//! let (l, r) = tuple_split::split_tuple_into_left::<(u8, f32), _>(t);
77//!
78//! assert_eq!(t, tupleops::concat_tuples(l, r));
79//! ```
80//!
81//! ### Right
82//!
83//! ```rust
84//! let t = (1, 1.0, "test");
85//!
86//! let (l, r) = tuple_split::split_tuple_into_right::<(&str,), _>(t);
87//!
88//! assert_eq!(t, tupleops::concat_tuples(l, r));
89//! ```
90//!
91//! ### Both
92//!
93//! ```rust
94//! let t = (1, 1.0, "test");
95//!
96//! let (l, r) = tuple_split::split_tuple_into::<(u8, f32), (&str,)>(t);
97//!
98//! assert_eq!(t, tupleops::concat_tuples(l, r));
99//! ```
100//!
101//! ## Tuple sizes
102//!
103//! By default, this crate operates with tuples of up to 16 elements, just like the [tupleops](https://crates.io/crates/tupleops) crate.
104//! If you want to use differently sized tuples, use the features `8`, `16`, `32`, `64`, `96`, `128`, `160`, `192`, `224` or `256` to set the maximum supported tuple
105//! size.
106//!
107//! The `dont_hurt_yourself_by_using_all_features` is there to prevent usage of tuples bigger than 8 if `cargo` is ran with the flag `--all-features`.
108//! Using a tuple size above 16 is highly discouraged as it will make compilation time unbearably long. Compilation time will increase exponentially.
109//! You have been warned.
110
111use core::marker::Tuple;
112
113use blk_count_macro::count;
114use tupleops::{ConcatTuples, TupleConcat};
115
116/// Type alias [Left](Left) equals [TupleSplit::Left](TupleSplit::Left)
117/// for any tuple which implements [TupleSplit](crate::TupleSplit) at the given MIDDLE.
118pub type Left<T, const MIDDLE: usize> = <T as TupleSplitAt<MIDDLE>>::Left;
119/// Type alias [Right](Right) equals [TupleSplit::Right](TupleSplit::Right)
120/// for any tuple which implements [TupleSplit](crate::TupleSplit) at the given MIDDLE.
121pub type Right<T, const MIDDLE: usize> = <T as TupleSplitAt<MIDDLE>>::Right;
122
123/// Tuples which may be split at index `MIDDLE` have the trait [TupleSplitAt](crate::TupleSplitAt),
124/// which, when split, returns [TupleSplitAt::Left](TupleSplitAt::Left), [TupleSplitAt::Right](TupleSplitAt::Right).
125///
126/// # Example
127///
128/// ```rust
129/// #![feature(generic_const_exprs)]
130///
131/// let t = (1, 1.0, "test");
132///
133/// let (l, r) = tuple_split::split_tuple_at::<2, _>(t);
134///
135/// assert_eq!(t, tupleops::concat_tuples(l, r));
136/// ```
137#[diagnostic::on_unimplemented(message = "`{Self}` cannot be split at index `{MIDDLE}`")]
138#[const_trait]
139pub trait TupleSplitAt<const MIDDLE: usize>: Tuple
140{
141    type Left: Tuple;
142    type Right: Tuple;
143
144    fn split_tuple_at(self) -> (Self::Left, Self::Right);
145}
146
147/// A trait for splitting a tuple up into two parts given a specified left part `L` and right part `R`. `L` and `R` must be the left and right part of `Self`.
148///
149/// Tuples will be split into parts `L` and `R`.
150///
151/// # Example
152///
153/// ```rust
154/// let t = (1, 1.0, "test");
155///
156/// let (l, r) = tuple_split::split_tuple_into::<(u8, f32), (&str,)>(t);
157///
158/// assert_eq!(t, tupleops::concat_tuples(l, r));
159/// ```
160#[diagnostic::on_unimplemented(message = "`{Self}` cannot be split up into `{L}` and `{R}`")]
161#[const_trait]
162pub trait TupleSplitInto<L, R>: ~const TupleSplitIntoLeft<L, Right = R> + ~const TupleSplitIntoRight<R, Left = L>
163where
164    L: Tuple,
165    R: Tuple
166{
167    fn split_tuple_into(self) -> (L, R);
168}
169
170impl<T, L, R> const TupleSplitInto<L, R> for T
171where
172    Self: ~const TupleSplitIntoLeft<L, Right = R> + ~const TupleSplitIntoRight<R, Left = L>,
173    L: Tuple,
174    R: Tuple
175{
176    fn split_tuple_into(self) -> (L, R)
177    {
178        self.split_tuple_into_left()
179    }
180}
181
182/// A trait for splitting a tuple up into two parts given a specified left part `L`. `L` must be a leftmost segment of `Self`.
183///
184/// Tuples will be split into parts `L` and [TupleSplitIntoLeft::Right](TupleSplitIntoLeft::Right).
185///
186/// # Example
187///
188/// ```rust
189/// let t = (1, 1.0, "test");
190///
191/// let (l, r) = tuple_split::split_tuple_into_left::<(u8, f32), _>(t);
192///
193/// assert_eq!(t, tupleops::concat_tuples(l, r));
194/// ```
195#[diagnostic::on_unimplemented(message = "`{L}` is not the left part of `{Self}`")]
196#[const_trait]
197pub trait TupleSplitIntoLeft<L>: Tuple
198where
199    L: Tuple
200{
201    type Right: Tuple;
202
203    fn split_tuple_into_left(self) -> (L, Self::Right);
204}
205
206/// A trait for splitting a tuple up into two parts given a specified right part `R`. `R` must be a rightmost segment of `Self`.
207///
208/// Tuples will be split into parts [TupleSplitIntoRight::Left](TupleSplitIntoRight::Left) and `R`.
209///
210/// # Example
211///
212/// ```rust
213/// let t = (1, 1.0, "test");
214///
215/// let (l, r) = tuple_split::split_tuple_into_right::<(&str,), _>(t);
216///
217/// assert_eq!(t, tupleops::concat_tuples(l, r));
218/// ```
219#[diagnostic::on_unimplemented(message = "`{R}` is not the right part of `{Self}`")]
220#[const_trait]
221pub trait TupleSplitIntoRight<R>: Tuple
222where
223    R: Tuple
224{
225    type Left: Tuple;
226
227    fn split_tuple_into_right(self) -> (Self::Left, R);
228}
229
230/// Splits tuple at a given index.
231///
232/// Index is specified as const generic `MIDDLE.
233///
234/// Tuple must be of trait `[TupleSplitAt](crate::TupleSplitAt)<MIDDLE>`.
235///
236/// Returns `([TupleSplitAt::Left](TupleSplitAt::Left), [TupleSplitAt::Right](TupleSplitAt::Right))` for the given Tuple and `MIDDLE`.
237///
238/// ```rust
239/// #![feature(generic_const_exprs)]
240///
241/// let t = (1, 1.0, "test");
242///
243/// let (l, r) = tuple_split::split_tuple_at::<2, _>(t);
244///
245/// assert_eq!(t, tupleops::concat_tuples(l, r));
246/// ```
247pub const fn split_tuple_at<const MIDDLE: usize, T>(tuple: T) -> (T::Left, T::Right)
248where
249    T: ~const TupleSplitAt<MIDDLE>
250{
251    tuple.split_tuple_at()
252}
253
254/// A trait for splitting a tuple up into two parts given a specified left part `L` and right part `R`. `L` and `R` must be the left and right part of `Self`.
255///
256/// Tuples will be split into parts `L` and `R`.
257///
258/// # Example
259///
260/// ```rust
261/// let t = (1, 1.0, "test");
262///
263/// let (l, r) = tuple_split::split_tuple_into::<(u8, f32), (&str,)>(t);
264///
265/// assert_eq!(t, tupleops::concat_tuples(l, r));
266/// ```
267pub const fn split_tuple_into<L, R>(tuple: ConcatTuples<L, R>) -> (L, R)
268where
269    L: Tuple,
270    R: Tuple,
271    (L, R): TupleConcat<L, R>,
272    ConcatTuples<L, R>: ~const TupleSplitInto<L, R>
273{
274    tuple.split_tuple_into()
275}
276
277/// Splits a tuple up into two parts given a specified left part `L`. `L` must be a leftmost segment of `Self`.
278///
279/// Tuples will be split into parts `L` and [TupleSplitIntoLeft::Right](TupleSplitIntoLeft::Right).
280///
281/// # Example
282///
283/// ```rust
284/// let t = (1, 1.0, "test");
285///
286/// let (l, r) = tuple_split::split_tuple_into_left::<(u8, f32), _>(t);
287///
288/// assert_eq!(t, tupleops::concat_tuples(l, r));
289/// ```
290pub const fn split_tuple_into_left<L, T>(tuple: T) -> (L, T::Right)
291where
292    L: Tuple,
293    T: ~const TupleSplitIntoLeft<L>
294{
295    tuple.split_tuple_into_left()
296}
297
298/// Splits a tuple up into two parts given a specified right part `R`. `R` must be a rightmost segment of `Self`.
299///
300/// Tuples will be split into parts [TupleSplitIntoRight::Left](TupleSplitIntoRight::Left) and `R`.
301///
302/// # Example
303///
304/// ```rust
305/// let t = (1, 1.0, "test");
306///
307/// let (l, r) = tuple_split::split_tuple_into_right::<(&str,), _>(t);
308///
309/// assert_eq!(t, tupleops::concat_tuples(l, r));
310/// ```
311pub const fn split_tuple_into_right<R, T>(tuple: T) -> (T::Left, R)
312where
313    R: Tuple,
314    T: ~const TupleSplitIntoRight<R>
315{
316    tuple.split_tuple_into_right()
317}
318
319macro_rules! impl_split_single {
320    (( $($types1:ident),* ), ( $($types2:ident),* )) => {
321        impl<$($types1,)* $($types2,)*> const TupleSplitAt<{count!($($types1),*)}> for ($($types1,)* $($types2,)*)
322        {
323            type Left = ($($types1,)*);
324            type Right = ($($types2,)*);
325
326            fn split_tuple_at(self) -> (Self::Left, Self::Right)
327            {
328                let ($($types1,)* $($types2,)*) = self;
329                (($($types1,)*), ($($types2,)*))
330            }
331        }
332
333        impl<$($types1,)* $($types2,)*> const TupleSplitIntoLeft<($($types1,)*)> for ($($types1,)* $($types2,)*)
334        {
335            type Right = ($($types2,)*);
336
337            fn split_tuple_into_left(self) -> (($($types1,)*), ($($types2,)*))
338            {
339                let ($($types1,)* $($types2,)*) = self;
340                (($($types1,)*), ($($types2,)*))
341            }
342        }
343        impl<$($types1,)* $($types2,)*> const TupleSplitIntoRight<($($types2,)*)> for ($($types1,)* $($types2,)*)
344        {
345            type Left = ($($types1,)*);
346
347            fn split_tuple_into_right(self) -> (($($types1,)*), ($($types2,)*))
348            {
349                let ($($types1,)* $($types2,)*) = self;
350                (($($types1,)*), ($($types2,)*))
351            }
352        }
353    };
354}
355macro_rules! impl_split_combinations {
356    ( (), ( $($types2:ident),* ) ) => {
357        impl_split_single!{(), ($($types2),*)}
358    };
359    (($t0:ident $(,$types1:ident)* ), ( $($types2:ident),* )) => {
360        impl_split_single!{($t0 $(,$types1)*), ($($types2),*)}
361
362        impl_split_combinations!{($($types1),*), ($t0 $(,$types2)*)}
363    };
364    (($($types:ident),*)) => {
365        impl_split_combinations!{($($types),*), ()}
366    }
367}
368macro_rules! impl_split_all {
369    (()) => {
370        impl_split_combinations!{()}
371    };
372    (($t0:ident $(,$types:ident)*)) => {
373        impl_split_combinations!{($t0 $(,$types)*)}
374
375        impl_split_all!{($($types),*)}
376    }
377}
378
379#[cfg(not(feature = "8"))]
380impl_split_all! {
381    (
382        _1, _2, _3, _4
383    )
384}
385
386#[cfg(feature = "8")]
387#[cfg(any(feature = "dont_hurt_yourself_by_using_all_features", not(feature = "16")))]
388impl_split_all! {
389    (
390        _1, _2, _3, _4, _5, _6, _7, _8
391    )
392}
393
394#[cfg(feature = "16")]
395#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
396#[cfg(not(feature = "32"))]
397impl_split_all! {
398    (
399        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16
400    )
401}
402
403#[cfg(feature = "32")]
404#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
405#[cfg(not(feature = "64"))]
406impl_split_all! {
407    (
408        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
409        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32
410    )
411}
412
413#[cfg(feature = "64")]
414#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
415#[cfg(not(feature = "96"))]
416impl_split_all! {
417    (
418        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
419        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
420        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
421        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64
422    )
423}
424
425#[cfg(feature = "96")]
426#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
427#[cfg(not(feature = "128"))]
428impl_split_all! {
429    (
430        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
431        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
432        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
433        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64,
434        _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80,
435        _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96
436    )
437}
438
439#[cfg(feature = "128")]
440#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
441#[cfg(not(feature = "160"))]
442impl_split_all! {
443    (
444        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
445        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
446        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
447        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64,
448        _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80,
449        _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96,
450        _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112,
451        _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128
452    )
453}
454
455#[cfg(feature = "160")]
456#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
457#[cfg(not(feature = "192"))]
458impl_split_all! {
459    (
460        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
461        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
462        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
463        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64,
464        _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80,
465        _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96,
466        _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112,
467        _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128,
468        _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144,
469        _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160
470    )
471}
472
473#[cfg(feature = "192")]
474#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
475#[cfg(not(feature = "224"))]
476impl_split_all! {
477    (
478        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
479        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
480        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
481        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64,
482        _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80,
483        _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96,
484        _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112,
485        _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128,
486        _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144,
487        _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160,
488        _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176,
489        _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192
490    )
491}
492
493#[cfg(feature = "224")]
494#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
495#[cfg(not(feature = "256"))]
496impl_split_all! {
497    (
498        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
499        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
500        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
501        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64,
502        _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80,
503        _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96,
504        _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112,
505        _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128,
506        _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144,
507        _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160,
508        _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176,
509        _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192,
510        _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208,
511        _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224
512    )
513}
514
515#[cfg(not(feature = "dont_hurt_yourself_by_using_all_features"))]
516#[cfg(feature = "256")]
517impl_split_all! {
518    (
519        _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16,
520        _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32,
521        _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48,
522        _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64,
523        _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80,
524        _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96,
525        _97, _98, _99, _100, _101, _102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112,
526        _113, _114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, _126, _127, _128,
527        _129, _130, _131, _132, _133, _134, _135, _136, _137, _138, _139, _140, _141, _142, _143, _144,
528        _145, _146, _147, _148, _149, _150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160,
529        _161, _162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, _174, _175, _176,
530        _177, _178, _179, _180, _181, _182, _183, _184, _185, _186, _187, _188, _189, _190, _191, _192,
531        _193, _194, _195, _196, _197, _198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208,
532        _209, _210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, _222, _223, _224,
533        _225, _226, _227, _228, _229, _230, _231, _232, _233, _234, _235, _236, _237, _238, _239, _240,
534        _241, _242, _243, _244, _245, _246, _247, _248, _249, _250, _251, _252, _253, _254, _255, _256
535    )
536}
537
538#[cfg(test)]
539mod tests
540{
541    use crate as tuple_split;
542
543    #[test]
544    fn test_split_concat()
545    {
546        let t: (u8, f32, &str) = (1, 1.0, "test");
547
548        let (l, r) = tuple_split::split_tuple_at::<0, _>(t);
549        assert_eq!(t, tupleops::concat_tuples(l, r));
550
551        let (l, r) = tuple_split::split_tuple_at::<1, _>(t);
552        assert_eq!(t, tupleops::concat_tuples(l, r));
553
554        let (l, r) = tuple_split::split_tuple_at::<2, _>(t);
555        assert_eq!(t, tupleops::concat_tuples(l, r));
556
557        let (l, r) = tuple_split::split_tuple_at::<3, _>(t);
558        assert_eq!(t, tupleops::concat_tuples(l, r));
559    }
560
561    #[cfg(feature = "8")]
562    #[test]
563    fn test()
564    {
565        let t = (1u8, 2u16, 3u32, 4u64, 5u128);
566
567        let (l1, r1) = tuple_split::split_tuple_into_left::<(u8, u16), _>(t);
568        let (l2, r2) = tuple_split::split_tuple_into_right::<(u32, u64, u128), _>(t);
569        let (l3, r3) = tuple_split::split_tuple_at::<2, _>(t);
570
571        assert_eq!(l1, l2);
572        assert_eq!(l2, l3);
573
574        assert_eq!(r1, r2);
575        assert_eq!(r2, r3);
576
577        assert_eq!(t, tupleops::concat_tuples(l1, r1));
578        assert_eq!(t, tupleops::concat_tuples(l2, r2));
579        assert_eq!(t, tupleops::concat_tuples(l3, r3));
580    }
581}
582
583/*mod private
584{
585    use core::{marker::Tuple, mem::ManuallyDrop};
586
587    use tupleops::{ConcatTuples, TupleConcat};
588
589    union TupleConcatTransmutation<L, R>
590    where
591        L: Tuple,
592        R: Tuple,
593        (L, R): TupleConcat<L, R, Type: Tuple>
594    {
595        split: ManuallyDrop<(ManuallyDrop<L>, ManuallyDrop<R>)>,
596        concat: ManuallyDrop<ConcatTuples<L, R>>
597    }
598
599    /// TODO: find a safe way to do this.
600    /// According to language specifications, the compiler can re-order elements in a tuple in any way in memory.
601    /// This function assumes they are in-order.
602    /// It works, i guess? (so far)
603    /// It's only because the compiler happens to do it like i assumed (most of the time, i think...)
604    #[deprecated(note = "This is undefined behaviour")]
605    pub const fn tuple_split_const_hold<L, R>(tuple: ConcatTuples<L, R>) -> (ManuallyDrop<L>, ManuallyDrop<R>)
606    where
607        L: Tuple,
608        R: Tuple,
609        (L, R): TupleConcat<L, R, Type: Tuple>
610    {
611        assert!(
612            core::mem::size_of::<(ManuallyDrop<L>, ManuallyDrop<R>)>() == core::mem::size_of::<ConcatTuples<L, R>>(),
613            "You just ran into undefined behaviour. Please report it on https://github.com/sigurd4/fn_zip/issues."
614        );
615        unsafe {
616            ManuallyDrop::into_inner(
617                TupleConcatTransmutation {
618                    concat: ManuallyDrop::new(tuple)
619                }
620                .split
621            )
622        }
623    }
624
625    /*#[deprecated(note = "This is undefined behaviour")]
626    pub const fn tuple_split_const<L, R>(tuple: ConcatTuples<L, R>) -> (L, R)
627    where
628        L: Tuple,
629        R: Tuple,
630        (L, R): TupleConcat<L, R, Type: Tuple>
631    {
632        let (left, right) = tuple_split_const_hold(tuple);
633        (ManuallyDrop::into_inner(left), ManuallyDrop::into_inner(right))
634    }*/
635}*/