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}