core_extensions_proc_macros/
lib.rs1#![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
16extern 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 let out = macro_utils::rewrap_macro_parameters(input_tokens);
134 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
212macro_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#[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_;