tuplestructops/lib.rs
1//! # Structural operations for tuples
2//!
3//! This crate implements splitting and joining tuples.
4//!
5//! The traits are implemented for tuples from zero len (ie, `()` unit) to 16.
6//! (More with with the `tuple_24` and `tuple_32` features enabled.)
7//!
8//! They are implemented for both tuples by value and reference, which either
9//! consume or borrow their inputs respectively.
10//!
11//! An example of [`TupleJoin`] by value:
12//! ```rust
13//! use tuplestructops::TupleJoin;
14//!
15//! let out = (1,'a',"b").join((1., 2.));
16//! println!("out {out:?}");
17//! ```
18//!
19//! [`TupleSplit`] does the converse. It relies on pattern matching to determine
20//! the split.
21//! ```rust
22//! use tuplestructops::TupleSplit;
23//!
24//! let out: (_, (_,_,_)) = (1,2,3,4,5).split();
25//! println!("out {out:?}");
26//! ```
27use seq_macro::seq;
28
29#[cfg(test)]
30mod test;
31
32mod macro_impl;
33
34/// Implement `join` for tuples.
35///
36/// `Self` is the left side of the join, and right is the `RHS` type parameter.
37pub trait TupleJoin<RHS>: seal::Sealed {
38 /// Joined output type. See [`TupleJoinOutput`] as an easy way to reference
39 /// this in other type contexts.
40 type Output;
41
42 /// Join two tuples. `self` is the left (prefix) and `other` is the right
43 /// (suffix).
44 /// ```rust
45 /// # use tuplestructops::TupleJoin;
46 /// let out: (_, _, _, _, _, _) = (1, 2, 3).join(('a', 'b', 'c'));
47 /// ```
48 /// Joining unit `()` tuples has no effect.
49 /// ```rust
50 /// # use tuplestructops::TupleJoin;
51 /// assert_eq!(().join((1, 2, 3)), (1, 2, 3));
52 /// ```
53 fn join(self, other: RHS) -> Self::Output;
54}
55
56/// Resulting type of joining tuples `L` and `R`. This is useful for referencing
57/// it in other type contexts. For example:
58/// ```rust
59/// # use std::path::PathBuf;
60/// # use tuplestructops::{TupleJoin, TupleJoinOutput};
61/// type DefaultBits = (String, PathBuf);
62///
63/// fn add_default<E>(extra: E) -> TupleJoinOutput<DefaultBits, E>
64/// where DefaultBits: TupleJoin<E>
65/// {
66/// ("hello".to_string(), PathBuf::from("/world")).join(extra)
67/// }
68/// ```
69pub type TupleJoinOutput<L, R> = <L as TupleJoin<R>>::Output;
70
71/// Split a tuple into left and right portions.
72pub trait TupleSplit<LHS, RHS>: seal::Sealed {
73 /// The left (prefix) and right (suffix) portions are defined by the `LHS`
74 /// and `RHS` trait type parameters. When invoking `split`, these will
75 /// generally be inferred by the calling context. For example, to split the
76 /// last three fields off a tuple, one can use:
77 /// ```rust
78 /// # use tuplestructops::TupleSplit;
79 /// let sometuple = (1, 2, 3, 4, 5, 'a', 'b', 'c');
80 /// let (left, (a, b, c)) = sometuple.split();
81 /// ```
82 /// Note that in this example `sometuple` can be any tuple type so long as
83 /// it has at least three fields.
84 fn split(self) -> (LHS, RHS);
85}
86
87mod seal {
88 pub trait Sealed {}
89}