lisbeth_tuple_tools/
append.rs

1/// Allows to append an element at the end of a tuple.
2///
3/// The generic type parameter `T` represents the type to be appended. It may
4/// be removed in the future, when GAT reach stable rust.
5pub trait TupleAppend<T> {
6    /// The type that is returned.
7    type Appended;
8
9    /// The appending function.
10    fn append(self, other: T) -> Self::Appended;
11}
12
13macro_rules! impl_tuple_append {
14    (
15        ( $( $left:ident ),* $(,)? ) + $right:ident $(,)?
16    ) => {
17        impl<$( $left, )* $right> TupleAppend<$right> for ( $( $left, )* ) {
18            type Appended = ( $( $left, )* $right, );
19
20            #[allow(non_snake_case)]
21            fn append(self, other: $right) -> Self::Appended {
22                let ( $( $left, )* ) = self;
23
24                ( $( $left, )* other, )
25            }
26        }
27    };
28}
29
30impl_tuple_append! { () + A }
31impl_tuple_append! { (A,) + B }
32impl_tuple_append! { (A, B) + C }
33impl_tuple_append! { (A, B, C) + D }
34impl_tuple_append! { (A, B, C, D) + E }
35impl_tuple_append! { (A, B, C, D, E) + F }
36impl_tuple_append! { (A, B, C, D, E, F) + G }
37impl_tuple_append! { (A, B, C, D, E, F, G) + H }
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn append_empty_tuple() {
45        let t: ((), (), (), (), ()) = ().append(()).append(()).append(()).append(()).append(());
46
47        // Note: there is acutally nothing to be checked, but let's assume so.
48        assert_eq!(t, ((), (), (), (), ()));
49    }
50
51    #[test]
52    fn append_up_to_eight() {
53        let t: (u8, u8, u8, u8, u8, u8, u8, u8) =
54            ().append(1)
55                .append(2)
56                .append(3)
57                .append(4)
58                .append(5)
59                .append(6)
60                .append(7)
61                .append(8);
62
63        assert_eq!(t, (1, 2, 3, 4, 5, 6, 7, 8));
64    }
65}