fast_macro/
lib.rs

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}