1#[macro_export]
2macro_rules! slice(
3 (@parse [$($stack:tt)*] $r:expr;$s:expr) => {
4 $crate::slice!(@final
5 [$($stack)* $crate::slice!(@convert $r, $s)]
6 )
7 };
8 (@parse [$($stack:tt)*] $r:expr) => {
9 $crate::slice!(@final [$($stack)* $crate::slice!(@convert $r)])
10 };
11 (@parse [$($stack:tt)*] $r:expr;$s:expr ,) => {
12 $crate::slice![@parse $in_dim, $out_dim, [$($stack)*] $r;$s]
13 };
14 (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr ,) => {
15 $crate::slice![@parse $in_dim, $out_dim, [$($stack)*] $r]
16 };
17 (@parse [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => {
18 match $r {
19 r => {
20 $crate::slice![@parse
21 [$($stack)* $crate::slice!(@convert r, $s),]
22 $($t)*
23 ]
24 }
25 }
26 };
27 (@parse [$($stack:tt)*] $r:expr, $($t:tt)*) => {
28 match $r {
29 r => {
30 $crate::slice![@parse
31 [$($stack)* $crate::slice!(@convert r),]
32 $($t)*
33 ]
34 }
35 }
36 };
37
38 (@parse []) => {
39 {
40 Slice0D { }
41 }
42 };
43
44 (@parse $($t:tt)*) => { compile_error!("Invalid syntax in slice![] call.") };
45
46 (@convert $r:expr) => {
47 $crate::slice::slice_dim::SliceDim::from($r)
48 };
49 (@convert $r:expr, $s:expr) => {
50 $crate::slice::slice_dim::SliceDim::from($r).step($s)
51 };
52
53 (@final [$dim1:expr]) => {
54 match $dim1 {
55 dim1 => $crate::slice::static_dim_slice::Slice1D {
56 index: [dim1],
57 }
58 }
59 };
60
61 (@final [$dim1:expr, $dim2:expr]) => {
62 $crate::slice::static_dim_slice::Slice2D {
63 index: [$dim1, $dim2],
64 }
65 };
66
67 (@final [$dim1:expr, $dim2:expr, $dim3:expr]) => {
68 $crate::slice::static_dim_slice::Slice3D {
69 index: [$dim1, $dim2, $dim3],
70 }
71 };
72
73 (@final [$dim1:expr, $dim2:expr, $dim3:expr, $dim4:expr]) => {
74 $crate::slice::static_dim_slice::Slice4D {
75 index: [$dim1, $dim2, $dim3, $dim4],
76 }
77 };
78
79 ($($t:tt)*) => {
80 $crate::slice![@parse
81 []
82 $($t)*
83 ]
84 };
85);
86
87#[macro_export]
88macro_rules! slice_dynamic {
89 (@parse [$($stack:tt)*] $r:expr;$s:expr) => {
90 $crate::slice_dynamic!(@final
91 [$($stack)* $crate::slice_dynamic!(@convert $r, $s)]
92 )
93 };
94 (@parse [$($stack:tt)*] $r:expr) => {
95 $crate::slice_dynamic!(@final [$($stack)* $crate::slice_dynamic!(@convert $r)])
96 };
97 (@parse [$($stack:tt)*] $r:expr;$s:expr ,) => {
98 $crate::slice_dynamic![@parse $in_dim, $out_dim, [$($stack)*] $r;$s]
99 };
100 (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr ,) => {
101 $crate::slice_dynamic![@parse $in_dim, $out_dim, [$($stack)*] $r]
102 };
103 (@parse [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => {
104 match $r {
105 r => {
106 $crate::slice_dynamic![@parse
107 [$($stack)* $crate::slice_dynamic!(@convert r, $s),]
108 $($t)*
109 ]
110 }
111 }
112 };
113 (@parse [$($stack:tt)*] $r:expr, $($t:tt)*) => {
114 match $r {
115 r => {
116 $crate::slice_dynamic![@parse
117 [$($stack)* $crate::slice_dynamic!(@convert r),]
118 $($t)*
119 ]
120 }
121 }
122 };
123 (@parse []) => {
124 {
125 $crate::slice::dynamic::Slice::From(&[])
126 }
127 };
128 (@parse $($t:tt)*) => { compile_error!("Invalid syntax in slice_dynamic![] call.") };
129
130 (@convert $r:expr) => {
131 $crate::slice::slice_dim::SliceDim::from($r)
132 };
133 (@convert $r:expr, $s:expr) => {
134 $crate::slice::slice_dim::SliceDim::from($r).step($s)
135 };
136
137 (@final [$($dim:expr),*]) => {{
138 let slice = [$($dim),*];
139 let slice_ref = &slice as &[$crate::slice::SliceDim];
140 $crate::slice::dynamic::Slice::from(slice_ref)
141 }};
142
143 ($($t:tt)*) => {
144 $crate::slice_dynamic![@parse
145 []
146 $($t)*
147 ]
148 };
149}
150
151#[cfg(test)]
152mod tests {
153 use crate::slice::dynamic::Slice;
154 use crate::slice::slice_dim::SliceDim;
155 use crate::slice::static_dim_slice::{Slice1D, Slice2D, Slice3D, Slice4D};
156
157 #[test]
158 fn test_slice_dynamic() {
159 let slice = slice_dynamic!(1..3;1, ..4;2, 5..;3);
160 assert_eq!(
161 slice,
162 Slice {
163 index: [
164 SliceDim {
165 start: Some(1),
166 end: Some(3),
167 step: Some(1)
168 },
169 SliceDim {
170 start: None,
171 end: Some(4),
172 step: Some(2)
173 },
174 SliceDim {
175 start: Some(5),
176 end: None,
177 step: Some(3)
178 },
179 SliceDim {
180 start: None,
181 end: None,
182 step: None
183 },
184 SliceDim {
185 start: None,
186 end: None,
187 step: None
188 },
189 SliceDim {
190 start: None,
191 end: None,
192 step: None
193 }
194 ],
195 len: 3
196 }
197 );
198 }
199
200 #[test]
201 fn test_slice_macro_1d() {
202 let slice = slice!(1..5;2);
203 assert_eq!(
204 slice,
205 Slice1D {
206 index: [SliceDim {
207 start: Some(1),
208 end: Some(5),
209 step: Some(2)
210 }]
211 }
212 );
213 }
214
215 #[test]
216 fn test_slice_macro_2d() {
217 let slice = slice!(..;2, 3..);
218 assert_eq!(
219 slice,
220 Slice2D {
221 index: [
222 SliceDim {
223 start: None,
224 end: None,
225 step: Some(2)
226 },
227 SliceDim {
228 start: Some(3),
229 end: None,
230 step: None
231 }
232 ]
233 }
234 );
235 }
236
237 #[test]
238 fn test_slice_macro_3d() {
239 let slice = slice!(1..3;1, ..4;2, 5..;3);
240 assert_eq!(
241 slice,
242 Slice3D {
243 index: [
244 SliceDim {
245 start: Some(1),
246 end: Some(3),
247 step: Some(1)
248 },
249 SliceDim {
250 start: None,
251 end: Some(4),
252 step: Some(2)
253 },
254 SliceDim {
255 start: Some(5),
256 end: None,
257 step: Some(3)
258 }
259 ]
260 }
261 );
262 }
263
264 #[test]
265 fn test_slice_macro_4d() {
266 let slice = slice!(..;1, 2..5, ..6;2, 7..9;3);
267 assert_eq!(
268 slice,
269 Slice4D {
270 index: [
271 SliceDim {
272 start: None,
273 end: None,
274 step: Some(1)
275 },
276 SliceDim {
277 start: Some(2),
278 end: Some(5),
279 step: None
280 },
281 SliceDim {
282 start: None,
283 end: Some(6),
284 step: Some(2)
285 },
286 SliceDim {
287 start: Some(7),
288 end: Some(9),
289 step: Some(3)
290 }
291 ]
292 }
293 );
294 }
295}