tuple_traits/cons.rs
1/// A base type that can be implemented by any type, which is used to build operations on top of.
2/// With this format it can be implemented to an infinite length, meaning that any operations built
3/// from it will work for any given length.
4pub trait Cons {
5 /// Left value of the cons, ideally the next value.
6 type Left;
7 /// Right value of the cons, another cons or unit if there are no more values.
8 type Right;
9}
10
11/// Helper macro to implement cons for all tuples of some length.
12///
13/// Tuple of length 0 (unit) must not implement cons, as it has neither a value nor a right side.
14macro_rules! impl_tuples {
15 // Base case, implement for when there is a single generic value.
16 ($T:ident) => {
17 impl<$T> Cons for ($T,) {
18 type Left = $T;
19 type Right = ();
20 }
21 };
22
23 // Recursive case, implement for when the first value is the left side, and recurse with the
24 // right side and rest of the list.
25 ($T:ident, $($Tail:ident),*) => {
26 impl<$T, $($Tail),*> Cons for ($T, $($Tail),*) {
27 type Left = $T;
28 type Right = ($($Tail),*,);
29 }
30
31 impl_tuples!($($Tail),*);
32 };
33}
34
35crate::tuple_list!(impl_tuples);
36
37#[cfg(test)]
38mod test {
39 use static_assertions::{assert_impl_all, assert_not_impl_all};
40
41 use super::*;
42
43 assert_impl_all!((usize,): Cons<Left = usize, Right = ()>);
44 assert_impl_all!((usize, usize): Cons<Left = usize, Right = (usize,)>);
45 assert_impl_all!((usize, usize, usize): Cons<Left = usize, Right = (usize, usize)>);
46
47 assert_not_impl_all!((): Cons);
48}