core_extensions_proc_macros/
lib.rs

1#![no_std]
2
3extern crate proc_macro;
4
5#[cfg(not(test))]
6use proc_macro as used_proc_macro;
7
8#[cfg(any(test, feature = "derive"))]
9extern crate proc_macro2;
10
11#[cfg(test)]
12use proc_macro2 as used_proc_macro;
13
14extern crate alloc;
15
16// #[cfg(test)]
17extern crate std;
18
19use crate::used_proc_macro::{Delimiter, Group, Punct, Spacing, Span, TokenStream, TokenTree};
20
21use core::iter::once;
22
23#[cfg(feature = "derive")]
24use proc_macro2::TokenStream as TokenStream2;
25
26#[cfg(feature = "derive")]
27mod derive;
28
29#[cfg(feature = "derive")]
30#[proc_macro_derive(ConstDefault, attributes(cdef))]
31pub fn derive_const_default(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
32    syn::parse(input)
33        .and_then(crate::derive::const_default_derive::derive_impl)
34        .unwrap_or_else(syn::Error::into_compile_error)
35        .into()
36}
37
38#[cfg(feature = "derive")]
39#[proc_macro_derive(TransparentNewtype, attributes(twrap))]
40pub fn derive_transparent_newtype(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
41    syn::parse(input)
42        .and_then(crate::derive::transparent_newtype_derive::derive_impl)
43        .unwrap_or_else(syn::Error::into_compile_error)
44        .into()
45}
46
47
48
49
50#[cfg(test)]
51mod test_utils;
52
53#[cfg(test)]
54mod tests;
55
56mod parsing_shared;
57
58mod splitting_generics;
59
60#[cfg(feature = "macro_utils")]
61#[macro_use]
62mod macro_utils_shared;
63
64#[cfg(feature = "macro_utils")]
65mod macro_utils;
66
67#[cfg(feature = "item_parsing")]
68mod item_parsing;
69
70
71#[cfg(feature = "macro_utils")]
72use crate::macro_utils_shared::Error;
73
74#[cfg(feature = "macro_utils")]
75type Result<T> = core::result::Result<T, Error>;
76
77
78#[cfg(feature = "macro_utils")]
79#[proc_macro_attribute]
80pub fn macro_attr(
81    attr: proc_macro::TokenStream,
82    item: proc_macro::TokenStream,
83) -> proc_macro::TokenStream {
84    crate::macro_utils::macro_attr(attr.into(), item.into())
85        .unwrap_or_else(Error::into_compile_error)
86        .into()
87}
88
89
90#[doc(hidden)]
91#[proc_macro]
92pub fn __priv_unwrap_bound(
93    input_tokens: proc_macro::TokenStream
94) -> proc_macro::TokenStream {
95    let input_tokens: TokenStream = input_tokens.into();
96
97    let mut iter = input_tokens.into_iter();
98
99    let ty_tt = iter.next().expect("__priv_unwrap_bound expected more tokens");
100    
101    let group = match &ty_tt {
102        TokenTree::Group(group) if group.delimiter() == Delimiter::None => group,
103        x => panic!("Expected a none-delimited group, found:\n{}", x)
104    };
105
106    let mut last_is_plus = true;
107
108    let mut ty = group.stream()
109        .into_iter()
110        .inspect(|tt|{
111             last_is_plus = mmatches!(tt, TokenTree::Punct(punc) if punc.as_char() == '+');
112        })
113        .collect::<TokenStream>();
114
115    if !last_is_plus {
116        ty.extend(once(TokenTree::Punct(Punct::new('+', Spacing::Alone))))
117    }
118
119    let args = TokenStream::new();
120
121    parsing_shared::parse_path_and_args("__priv_unwrap_bound", &mut iter, args, |args| {
122        args.extend(once(TokenTree::Group(Group::new(Delimiter::Parenthesis, ty))));
123    }).into()
124}
125
126
127#[cfg(feature = "macro_utils")]
128#[doc(hidden)]
129#[proc_macro]
130pub fn __priv_rewrap_macro_parameters(input_tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
131    let input_tokens: TokenStream = input_tokens.into();
132    //std::println!("\n----------------------------\n\n{:?}", input_tokens);
133    let out = macro_utils::rewrap_macro_parameters(input_tokens);
134    //std::println!("\n\n{:?}", out);
135    out.into()
136}
137
138#[cfg(feature = "macro_utils")]
139#[proc_macro]
140pub fn count_tts(input_tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
141    let input_tokens: TokenStream = input_tokens.into();
142    let out = macro_utils::count_tts(input_tokens).unwrap_or_else(Error::into_compile_error); 
143    out.into()
144}
145
146#[cfg(feature = "macro_utils")]
147#[proc_macro]
148pub fn gen_ident_range(input_tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
149    let input_tokens: TokenStream = input_tokens.into();
150    let out = macro_utils::gen_ident_range(input_tokens).unwrap_or_else(Error::into_compile_error); 
151    out.into()
152}
153
154
155#[cfg(feature = "macro_utils")]
156#[proc_macro]
157pub fn tokens_method(input_tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
158    let input_tokens: TokenStream = input_tokens.into();
159    let out = macro_utils::tokens_method(input_tokens).unwrap_or_else(Error::into_compile_error); 
160    out.into()
161}
162
163
164
165#[doc(hidden)]
166#[proc_macro]
167pub fn __priv_split_generics(input_tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
168    split_generics(input_tokens.into()).into()
169}
170
171fn split_generics(input: TokenStream) -> TokenStream {
172    use crate::{
173        parsing_shared::out_parenthesized,
174        splitting_generics::{PostGenericsParser, SplitGenerics}
175    };
176
177    struct UnparsedPostGenerics {
178        output: TokenStream,
179        output_span: Span,
180    }
181
182    impl PostGenericsParser for UnparsedPostGenerics {
183        fn consume_token(&mut self, sg: &SplitGenerics, tt: TokenTree) {
184            self.output_span = sg.last_span();
185            self.output.extend(once(tt));
186        }
187        fn write_tokens(self, ts: &mut TokenStream) {
188            out_parenthesized(self.output, self.output_span, ts)
189        }
190    }
191
192    let mut input = input.into_iter();
193    let macro_invoc = parsing_shared::panicking_parse_macro_invocation(&mut input);
194
195    SplitGenerics::new(input).split_generics(macro_invoc, TokenStream::new(), UnparsedPostGenerics{
196        output: TokenStream::new(),
197        output_span: Span::call_site(),
198    })
199}
200
201#[cfg(feature = "item_parsing")]
202#[doc(hidden)]
203#[proc_macro]
204pub fn __priv_split_impl(input_tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
205    crate::item_parsing::split_impl(input_tokens.into()).into()
206}
207
208
209
210
211
212// MSRV is 1.41.0, matches was stabilized in 1.42.0
213macro_rules! mmatches {
214    ( $expr:expr, $pat:pat $(if $cond:expr)?)=>{
215        match $expr {
216            $pat  $(if $cond)? =>true,
217            _=>false
218        }
219    };
220} use mmatches;
221
222// Purely for performance
223#[allow(unused_macros)]
224macro_rules! try_ {
225    ( $expr:expr )=>{
226        match $expr {
227            Ok(x) => x,
228            Err(e) => return Err(e),
229        }
230    };
231    ( $expr:expr, map_err = |$e:tt| $map_err:expr )=>{
232        match $expr {
233            Ok(x) => x,
234            Err($e) => return Err($map_err),
235        }
236    };
237}
238#[allow(unused_imports)]
239use try_;