multiversion_macros/
lib.rs1extern 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 match cfg::transform(meta) {
108 Ok(meta) => {
109 quote! {
110 #[cfg(#meta)]
111 #input
112 }
113 }
114 Err(err) => err.to_compile_error(),
115 }
116 .into()
117}
118
119#[proc_macro_attribute]
120pub fn target_cfg_attr_impl(
121 attr: proc_macro::TokenStream,
122 input: proc_macro::TokenStream,
123) -> proc_macro::TokenStream {
124 let mut meta = parse_macro_input!(attr with Punctuated::parse_terminated);
125 let input = TokenStream::from(input);
126
127 let attr = meta.pop().unwrap();
128 match cfg::transform(meta) {
129 Ok(meta) => {
130 quote! {
131 #[cfg_attr(#meta, #attr)]
132 #input
133 }
134 }
135 Err(err) => err.to_compile_error(),
136 }
137 .into()
138}
139
140#[proc_macro]
141pub fn target_cfg_f_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
142 let meta = parse_macro_input!(input with Punctuated::parse_terminated);
143
144 match cfg::transform(meta) {
145 Ok(meta) => {
146 quote! {
147 cfg!(#meta)
148 }
149 }
150 Err(err) => err.to_compile_error(),
151 }
152 .into()
153}
154
155#[proc_macro]
156pub fn match_target(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
157 let input = TokenStream::from(input);
158 quote! {
159 __multiversion::match_target!{ #input }
160 }
161 .into()
162}
163
164#[proc_macro]
165pub fn match_target_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
166 let match_target = parse_macro_input!(input as match_target::MatchTarget);
167 match_target.into_token_stream().into()
168}