variyak/
lib.rs

1/*!
2
3This crate provides a macro `call_variadic` which can be used to construct boilerplate code
4to call variadic functions using data from a container such as a Vec.
5
6# Example
7```rust,ignore
8    let data = vec![1, 2];
9    call_variadic!(
10        my_func(arg, ...)   // func
11        data,               // container
12        n,                  // index
13        data[n],            // expand
14        2,                  // limit
15    );
16
17    // Generates:
18    //     let container_len = data.len();
19    //     match container_len {
20    //         0 => my_func(arg),
21    //         1 => my_func(arg, {
22    //             let n = 0;
23    //             data[n]
24    //         }),
25    //         2 => my_func(
26    //             arg,
27    //             {
28    //                 let n = 0;
29    //                 data[n]
30    //             },
31    //             {
32    //                 let n = 1;
33    //                 data[n]
34    //             },
35    //         ),
36    //         _ => panic!("expected container size of: 0..=2 got data.len(): {}", container_len)
37    //         )),
38    //     }
39*/
40
41pub mod export {
42    pub use seq_macro::seq;
43}
44
45/**
46Call a variadic function given a container
47
48* func: function call, `...` is the variadic arguments
49* container: container identifier
50* index: index identifier
51* expand: argument expression: get `argument` at index `n`
52* limit: maximum number of arguments to expand
53
54# Panics
55
56Panics if size of container is greater than `limit`
57*/
58#[macro_export]
59macro_rules! call_variadic {
60    (
61        $func:ident $( :: $func_tail:ident )* ( $($args:tt)* ), $container:ident, $index:ident, $($expand:expr)+, $limit:literal
62    ) => (
63        call_variadic! { @munch
64            (func: $func)
65            (func_tail: $($func_tail)*)
66            (pre: )
67
68            /* to parse */
69            (args: $($args)*)
70
71            (container: $container)
72            (index: $index)
73            (expand: $($expand)+)
74            (limit: $limit)
75        }
76    );
77
78    (@munch
79        (func: $func:ident)
80        (func_tail: $($func_tail:ident)*)
81        (pre: $($pre:tt)*)
82        (post: $($post:tt)*)
83
84        (container: $container:ident)
85        (index: $index:ident)
86        (expand: $($expand:expr)+)
87        (limit: $limit:literal)
88     ) => (
89         $crate::export::seq!(__N in 0..=$limit {{
90             let container_len = $container.len();
91             match container_len {
92                 #(
93                     __N => {
94                         $crate::export::seq!(__I in 0..__N {
95                             $func $(:: $func_tail)* (
96                                 $($pre,)*
97                                 #( {
98                                     let $index = __I;
99                                     $($expand)+
100                                 },)*
101                                 $($post),*
102                                 )
103                         })
104                     }
105                  )*
106                     _ => {
107                         panic!("expected container size of: 0..={} got {}.len(): {}",
108                         stringify!($limit),
109                         stringify!($container),
110                         container_len
111                         )
112                     }
113             }
114         }})
115    );
116
117    (@munch
118        (func: $func:ident)
119        (func_tail: $($func_tail:ident)*)
120        (pre: $($pre:tt)*)
121        (args: ... $(, $post:expr)* $(,)?)
122
123        $container:tt
124        $index:tt
125        (expand: $($expand:tt)+)
126        $limit:tt
127    ) => (
128        call_variadic! { @munch
129            (func: $func)
130            (func_tail: $($func_tail)*)
131            (pre: $($pre)*)
132            (post: $($post)*)
133
134            $container
135            $index
136            (expand: $($expand)+)
137            $limit
138        }
139    );
140
141    (@munch
142        $func:tt
143        (func_tail: $($func_tail:tt)*)
144        (pre: $($pre:tt)*)
145        (args: $expr:expr, $($rest:tt)*)
146
147        $container:tt
148        $index:tt
149        (expand: $($expand:tt)+)
150        $limit:tt
151    ) => (
152        call_variadic! { @munch
153            $func
154            (func_tail: $($func_tail)*)
155            (pre: $($pre)* $expr)
156            (args: $($rest)*)
157
158            $container
159            $index
160            (expand: $($expand)+)
161            $limit
162        }
163    );
164}