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}