wrapped_list/
lib.rs

1//! # wrapped-list
2//!
3//! This crate provides macros which allow you to create lists of elements
4//! that are wrappped by an object, function, or another macro at compile time.
5//!
6//! ```ignore
7//! wrapped_list![Box::new; value_1, value_2, ...]
8//! ```
9//!
10//! Expands to:
11//!
12//! ```ignore
13//! [Box::new(value_1), Box::new(value_2), ...]
14//! ```
15//!
16//! With this you can:
17//!
18//! - [Wrap values with a tuple struct or enum](#wrap-values-with-a-tuple-struct-or-enum)
19//! - [Wrap values with an object or function](#wrap-values-with-an-object-or-function)
20//! - [Wrap values with a macro](#wrap-values-with-a-macro)
21//!
22//! ## Examples
23//!
24//! ### Wrap values with a tuple struct or enum
25//!
26//! ```
27//! use wrapped_list::wrapped_list;
28//!
29//! #[derive(Debug, PartialEq, Eq)]
30//! struct Wrapper(i32);
31//!
32//! let wrapped_items = wrapped_list![Wrapper; 1, 2, 3, 4];
33//!
34//! assert_eq!(wrapped_items, [Wrapper(1), Wrapper(2), Wrapper(3), Wrapper(4)]);
35//! ```
36//!
37//! ### Wrap values with an object or function
38//!
39//! ```
40//! use wrapped_list::wrapped_list;
41//!
42//! let boxed_items = wrapped_list![Box::new; 1, 2, 3];
43//!
44//! assert_eq!(boxed_items, [Box::new(1), Box::new(2), Box::new(3)])
45//! ```
46//!
47//! ```
48//! use wrapped_list::wrapped_list;
49//!
50//! let func = |x| x * 2;
51//!
52//! let doubled = wrapped_list![func; 1, 2, 3];
53//!
54//! assert_eq!(doubled, [2, 4, 6]);
55//! ```
56//!
57//! ### Wrap values with a macro
58//!
59//! ```
60//! use wrapped_list::wrapped_list;
61//!
62//! macro_rules! add_one {
63//!     ($e:expr) => {
64//!         $e + 1
65//!     };
66//! }
67//!
68//! let one_more = wrapped_list![add_one!; 1, 2, 3];
69//!
70//! assert_eq!(one_more, [2, 3, 4]);
71//! ```
72
73/// Macro to wrap a list of values with a function, object, or another macro.
74///
75/// See the [examples](crate#examples) to learn more.
76#[macro_export]
77macro_rules! wrapped_list {
78    [$wrapper:path ; $($e:expr),* $(,)?] => {
79        [$($wrapper($e)),*]
80    };
81    [$wrapper:ident! ; $($e:expr),* $(,)?] => {
82        [$($wrapper!($e)),*]
83    }
84}
85
86/// Functions identically to [wrapped_list], but the list is returned as a vector.
87#[macro_export]
88macro_rules! wrapped_vec {
89    [$wrapper:path ; $($e:expr),* $(,)?] => {
90        vec![$($wrapper($e)),*]
91    };
92    [$wrapper:ident! ; $($e:expr),* $(,)?] => {
93        vec![$($wrapper!($e)),*]
94    }
95}
96
97/// Functions identically to [wrapped_list], but the list is returned as a tuple.
98#[macro_export]
99macro_rules! wrapped_tuple {
100    ($wrapper:path ; $($e:expr),* $(,)?) => {
101        ($($wrapper($e)),*)
102    };
103    ($wrapper:ident! ; $($e:expr),* $(,)?) => {
104        ($($wrapper!($e)),*)
105    }
106}
107
108#[doc(hidden)]
109#[cfg(test)]
110mod tests {
111    use duplicate::duplicate_item;
112
113    #[derive(PartialEq, Eq, Debug)]
114    struct Wrapper(i32);
115
116    #[derive(PartialEq, Eq, Debug)]
117    struct ComplexWrapper {
118        wrapped_item: i32,
119    }
120
121    impl ComplexWrapper {
122        pub fn new(item: i32) -> Self {
123            ComplexWrapper { wrapped_item: item }
124        }
125    }
126
127    fn wrapper_function1(input: i32) -> i32 {
128        input * 10
129    }
130
131    fn wrapper_function2(input: i32) -> bool {
132        input > 2
133    }
134
135    macro_rules! wrapper_macro1 {
136        ($e:expr) => {
137            Wrapper($e)
138        };
139    }
140
141    macro_rules! add_one {
142        ($e:expr) => {
143            $e + 1
144        };
145    }
146
147    macro_rules! wrapper_macro2 {
148        ($e:expr) => {
149            Wrapper(add_one!($e))
150        };
151    }
152
153    #[duplicate_item(
154        wrapper                test_name;
155        [Wrapper]              [wrapper_test];
156        [ComplexWrapper::new]  [complex_wrapper_test];
157        [Box::new]             [box_test];
158        [wrapper_function1]    [function_test1];
159        [wrapper_function2]    [function_test2];
160    )]
161    #[test]
162    fn test_name() {
163        let my_list = [wrapper(1)];
164        assert_eq!(my_list, wrapped_list![wrapper; 1]);
165        let my_list = [wrapper(1), wrapper(2)];
166        assert_eq!(my_list, wrapped_list![wrapper; 1, 2]);
167        let my_list = [wrapper(1), wrapper(2), wrapper(3)];
168        assert_eq!(my_list, wrapped_list![wrapper; 1, 2, 3]);
169        let my_list = [wrapper(1), wrapper(2), wrapper(3), wrapper(4)];
170        assert_eq!(my_list, wrapped_list![wrapper; 1, 2, 3, 4]);
171    }
172
173    #[duplicate_item(
174        wrapper                test_name;
175        [Wrapper]              [vec_wrapper_test];
176        [ComplexWrapper::new]  [vec_complex_wrapper_test];
177        [Box::new]             [vec_box_test];
178        [wrapper_function1]    [vec_function_test1];
179        [wrapper_function2]    [vec_function_test2];
180    )]
181    #[test]
182    fn test_name() {
183        let my_list = vec![wrapper(1)];
184        assert_eq!(my_list, wrapped_vec![wrapper; 1]);
185        let my_list = vec![wrapper(1), wrapper(2)];
186        assert_eq!(my_list, wrapped_vec![wrapper; 1, 2]);
187        let my_list = vec![wrapper(1), wrapper(2), wrapper(3)];
188        assert_eq!(my_list, wrapped_vec![wrapper; 1, 2, 3]);
189        let my_list = vec![wrapper(1), wrapper(2), wrapper(3), wrapper(4)];
190        assert_eq!(my_list, wrapped_vec![wrapper; 1, 2, 3, 4]);
191    }
192
193    #[duplicate_item(
194        wrapper                test_name;
195        [Wrapper]              [tuple_wrapper_test];
196        [ComplexWrapper::new]  [tuple_complex_wrapper_test];
197        [Box::new]             [tuple_box_test];
198        [wrapper_function1]    [tuple_function_test1];
199        [wrapper_function2]    [tuple_function_test2];
200    )]
201    #[test]
202    fn test_name() {
203        let my_list = wrapper(1);
204        assert_eq!(my_list, wrapped_tuple!(wrapper; 1));
205        let my_list = (wrapper(1), wrapper(2));
206        assert_eq!(my_list, wrapped_tuple!(wrapper; 1, 2));
207        let my_list = (wrapper(1), wrapper(2), wrapper(3));
208        assert_eq!(my_list, wrapped_tuple!(wrapper; 1, 2, 3));
209        let my_list = (wrapper(1), wrapper(2), wrapper(3), wrapper(4));
210        assert_eq!(my_list, wrapped_tuple!(wrapper; 1, 2, 3, 4));
211    }
212
213    #[test]
214    fn trailing_commas() {
215        let my_list = [Wrapper(1)];
216        assert_eq!(my_list, wrapped_list![Wrapper; 1,]);
217        let my_list = [Wrapper(1), Wrapper(2)];
218        assert_eq!(my_list, wrapped_list![Wrapper; 1, 2,]);
219        let my_list = [Wrapper(1), Wrapper(2), Wrapper(3)];
220        assert_eq!(my_list, wrapped_list![Wrapper; 1, 2, 3,]);
221        let my_list = [Wrapper(1), Wrapper(2), Wrapper(3), Wrapper(4)];
222        assert_eq!(my_list, wrapped_list![Wrapper; 1, 2, 3, 4,]);
223    }
224
225    #[duplicate_item(
226        macro_name        test_name;
227        [wrapper_macro1]  [macro_test1];
228        [wrapper_macro2]  [macro_test2];
229    )]
230    #[test]
231    fn test_name() {
232        let my_list = [macro_name!(1)];
233        assert_eq!(my_list, wrapped_list![macro_name!; 1]);
234        let my_list = [macro_name!(1), macro_name!(2)];
235        assert_eq!(my_list, wrapped_list![macro_name!; 1, 2]);
236        let my_list = [macro_name!(1), macro_name!(2), macro_name!(3)];
237        assert_eq!(my_list, wrapped_list![macro_name!; 1, 2, 3]);
238        let my_list = [
239            macro_name!(1),
240            macro_name!(2),
241            macro_name!(3),
242            macro_name!(4),
243        ];
244        assert_eq!(my_list, wrapped_list!(macro_name!; 1, 2, 3, 4));
245    }
246
247    #[test]
248    fn trailing_commas_macro() {
249        let my_list = [wrapper_macro2!(1)];
250        assert_eq!(my_list, wrapped_list![wrapper_macro2!; 1,]);
251        let my_list = [wrapper_macro2!(1), wrapper_macro2!(2)];
252        assert_eq!(my_list, wrapped_list![wrapper_macro2!; 1, 2,]);
253        let my_list = [wrapper_macro2!(1), wrapper_macro2!(2), wrapper_macro2!(3)];
254        assert_eq!(my_list, wrapped_list![wrapper_macro2!; 1, 2, 3,]);
255        let my_list = [
256            wrapper_macro2!(1),
257            wrapper_macro2!(2),
258            wrapper_macro2!(3),
259            wrapper_macro2!(4),
260        ];
261        assert_eq!(my_list, wrapped_list![wrapper_macro2!; 1, 2, 3, 4,]);
262    }
263}