1use itertools::Itertools;
2use proc_macro::{Span, TokenStream};
3use quote::quote;
4use syn::*;
5
6#[proc_macro_attribute]
7pub fn main(_: TokenStream, input: TokenStream) -> TokenStream {
8 let input = parse_macro_input!(input as ItemFn);
9
10 assert!(input.sig.asyncness.is_some(), "Main must be async");
11
12 let block = input.block;
13
14 let output = quote! {
15 fn main() {
16 fast::run(async move {
17 #block
18 })
19 }
20 };
21
22 output.into()
23}
24
25#[proc_macro]
26pub fn swizzle(_: TokenStream) -> TokenStream {
27 let pattern = |swizzle: [char; 4]| {
28 (1..=4).flat_map(move |len| {
29 let components = swizzle.iter().enumerate().map(|(i, &c)| (c, i as u32));
30
31 std::iter::repeat_n(components, len)
32 .multi_cartesian_product()
33 .collect::<Vec<_>>()
34 })
35 };
36
37 let patterns = (pattern)(['x', 'y', 'z', 'w'])
38 .chain((pattern)(['r', 'g', 'b', 'a']))
39 .map(|perm| {
40 let (chars, indices): (Vec<_>, Vec<_>) = perm.into_iter().unzip();
41 let pattern: String = chars.into_iter().collect();
42 let name = Ident::new(
43 &(pattern[..1].to_uppercase() + &pattern[1..]),
44 Span::call_site().into(),
45 );
46 let len = indices.len();
47
48 quote! {
49 pub struct #name;
50 impl Pattern for #name {
51 type Indices = [u32; #len];
52 const MASK: Self::Indices = [#(#indices),*];
53 }
54 }
55 });
56
57 quote! {
58 #(#patterns)*
59 }
60 .into()
61}