vec_unpack/
lib.rs

1/// Creates a [`Vec`] containing the arguments.
2/// [`vecu!`] unpacks iterable variables marked with `@`.
3///
4/// ```
5/// use vec_unpack::*;
6/// let a = [2, 3];
7/// let b = vecu![0, 1, @a, 4, 5];
8/// assert_eq!(b, vec![0, 1, 2, 3, 4, 5]);
9/// ```
10#[macro_export]
11macro_rules! vecu {
12    () => {
13        Vec::new()
14    };
15    ($($x:expr),+ $(,)?) => {
16        vec![$($x),+]
17    };
18    ($($input:tt)*) => {
19        {
20            let mut v = Vec::new();
21            vecu_inner!(v, $($input)*);
22            v
23        }
24    };
25}
26
27/// Used in [`vecu!`].
28#[macro_export]
29macro_rules! vecu_inner {
30    ($v:ident,) => {};
31    ($v:ident, $x:expr) => {
32        $v.push($x);
33    };
34    ($v:ident, @$x:expr) => {
35        $v.extend($x);
36    };
37    ($v:ident, $x:expr, $($tail:tt)*) => {
38        $v.push($x);
39        vecu_inner!($v, $($tail)*)
40    };
41    ($v:ident, @$x:expr, $($tail:tt)*) => {
42        $v.extend($x);
43        vecu_inner!($v, $($tail)*)
44    };
45}
46
47#[cfg(test)]
48mod tests {
49    use super::vecu;
50
51    #[test]
52    fn empty() {
53        let vu: Vec<i32> = vecu![];
54        let v: Vec<i32> = vec![];
55        assert_eq!(vu, v);
56    }
57
58    #[test]
59    fn with_tail_comma() {
60        let a = [2, 3];
61        let b = vecu![0, 1, @a, 4, 5,];
62        assert_eq!(b, vec![0, 1, 2, 3, 4, 5]);
63    }
64
65    #[test]
66    fn without_tail_comma() {
67        let a = [2, 3];
68        let b = vecu![0, 1, @a, 4, 5];
69        assert_eq!(b, vec![0, 1, 2, 3, 4, 5]);
70    }
71
72    #[test]
73    fn multi_unpack() {
74        let a = [1, 2];
75        let b = [3, 4, 5];
76        let c = vecu![0, @a, @b, 6, 7];
77        assert_eq!(c, vec![0, 1, 2, 3, 4, 5, 6, 7]);
78    }
79
80    #[test]
81    fn without_unpack() {
82        assert_eq!(vecu![0, 1, 2], vec![0, 1, 2]);
83    }
84
85    #[test]
86    fn unpack_only() {
87        let a = [1, 2];
88        let b = vecu![@a];
89        assert_eq!(b, vec![1, 2]);
90    }
91}