Skip to main content

multiversion_macros/
lib.rs

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