fmc_noise_multiversion_macros/
lib.rs

1//! Implementation crate for `multiversion`.
2extern crate proc_macro;
3
4mod cfg;
5mod dispatcher;
6mod match_target;
7mod multiversion;
8mod target;
9mod util;
10
11use proc_macro2::TokenStream;
12use quote::{quote, ToTokens};
13use syn::{parse::Nothing, parse_macro_input, punctuated::Punctuated, ItemFn};
14
15#[proc_macro_attribute]
16pub fn multiversion(
17    attr: proc_macro::TokenStream,
18    input: proc_macro::TokenStream,
19) -> proc_macro::TokenStream {
20    let func = parse_macro_input!(input as ItemFn);
21    match multiversion::make_multiversioned_fn(attr.into(), func) {
22        Ok(tokens) => tokens.into_token_stream(),
23        Err(err) => err.to_compile_error(),
24    }
25    .into()
26}
27
28#[proc_macro_attribute]
29pub fn target(
30    attr: proc_macro::TokenStream,
31    input: proc_macro::TokenStream,
32) -> proc_macro::TokenStream {
33    let target = parse_macro_input!(attr as syn::LitStr);
34    let func = parse_macro_input!(input as ItemFn);
35    match target::make_target_fn(target, func) {
36        Ok(tokens) => tokens.into_token_stream(),
37        Err(err) => err.to_compile_error(),
38    }
39    .into()
40}
41
42#[proc_macro_attribute]
43pub fn inherit_target(
44    attr: proc_macro::TokenStream,
45    input: proc_macro::TokenStream,
46) -> proc_macro::TokenStream {
47    parse_macro_input!(attr as Nothing);
48    let func = parse_macro_input!(input as ItemFn);
49    quote! {
50        __multiversion::inherit_target! { #func }
51    }
52    .into()
53}
54
55#[proc_macro]
56pub fn selected_target(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
57    parse_macro_input!(input as Nothing);
58    quote! {
59        __multiversion::FEATURES
60    }
61    .into()
62}
63
64#[proc_macro_attribute]
65pub fn target_cfg(
66    attr: proc_macro::TokenStream,
67    input: proc_macro::TokenStream,
68) -> proc_macro::TokenStream {
69    let attr = TokenStream::from(attr);
70    let input = TokenStream::from(input);
71    quote! {
72        __multiversion::target_cfg!{ [#attr] #input }
73    }
74    .into()
75}
76
77#[proc_macro_attribute]
78pub fn target_cfg_attr(
79    attr: proc_macro::TokenStream,
80    input: proc_macro::TokenStream,
81) -> proc_macro::TokenStream {
82    let attr = TokenStream::from(attr);
83    let input = TokenStream::from(input);
84    quote! {
85        __multiversion::target_cfg_attr!{ [#attr] #input }
86    }
87    .into()
88}
89
90#[proc_macro]
91pub fn target_cfg_f(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
92    let input = TokenStream::from(input);
93    quote! {
94        __multiversion::target_cfg_f!{ #input }
95    }
96    .into()
97}
98
99#[proc_macro_attribute]
100pub fn target_cfg_impl(
101    attr: proc_macro::TokenStream,
102    input: proc_macro::TokenStream,
103) -> proc_macro::TokenStream {
104    let meta = parse_macro_input!(attr with Punctuated::parse_terminated);
105    let input = TokenStream::from(input);
106
107    let meta = cfg::transform(meta);
108    quote! {
109        #[cfg(#meta)]
110        #input
111    }
112    .into()
113}
114
115#[proc_macro_attribute]
116pub fn target_cfg_attr_impl(
117    attr: proc_macro::TokenStream,
118    input: proc_macro::TokenStream,
119) -> proc_macro::TokenStream {
120    let mut meta = parse_macro_input!(attr with Punctuated::parse_terminated);
121    let input = TokenStream::from(input);
122
123    let attr = meta.pop().unwrap();
124    let meta = cfg::transform(meta);
125    quote! {
126        #[cfg_attr(#meta, #attr)]
127        #input
128    }
129    .into()
130}
131
132#[proc_macro]
133pub fn target_cfg_f_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
134    let meta = parse_macro_input!(input with Punctuated::parse_terminated);
135
136    let meta = cfg::transform(meta);
137    quote! {
138        cfg!(#meta)
139    }
140    .into()
141}
142
143#[proc_macro]
144pub fn match_target(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
145    let input = TokenStream::from(input);
146    quote! {
147        __multiversion::match_target!{ #input }
148    }
149    .into()
150}
151
152#[proc_macro]
153pub fn match_target_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
154    let match_target = parse_macro_input!(input as match_target::MatchTarget);
155    match_target.into_token_stream().into()
156}