1#![allow(clippy::manual_map)]
26#![allow(clippy::too_many_arguments)]
27
28mod any;
29mod const_value;
30mod context;
31mod from_value;
32mod function;
33mod hash;
34mod inst_display;
35mod item;
36mod macro_;
37mod module;
38mod opaque;
39mod parse;
40mod path_in;
41mod quote;
42mod spanned;
43mod to_tokens;
44mod to_value;
45
46use self::context::{Context, Tokens};
47
48use ::quote::format_ident;
49use proc_macro2::TokenStream;
50use syn::{Generics, Path};
51
52const RUNE: &str = "rune";
53
54#[proc_macro]
55#[doc(hidden)]
56pub fn quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
57 let input = proc_macro2::TokenStream::from(input);
58 let parser = crate::quote::Quote::new();
59
60 let output = match parser.parse(input) {
61 Ok(output) => output,
62 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
63 };
64
65 output.into()
66}
67
68#[proc_macro_attribute]
69#[doc(hidden)]
70pub fn function(
71 attrs: proc_macro::TokenStream,
72 item: proc_macro::TokenStream,
73) -> proc_macro::TokenStream {
74 let attrs = syn::parse_macro_input!(attrs with crate::function::FunctionAttrs::parse);
75 let function = syn::parse_macro_input!(item with crate::function::Function::parse);
76
77 let output = match function.expand(attrs) {
78 Ok(output) => output,
79 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
80 };
81
82 output.into()
83}
84
85#[proc_macro_attribute]
86#[doc(hidden)]
87pub fn macro_(
88 attrs: proc_macro::TokenStream,
89 item: proc_macro::TokenStream,
90) -> proc_macro::TokenStream {
91 let attrs = syn::parse_macro_input!(attrs with crate::macro_::Config::parse);
92 let macro_ = syn::parse_macro_input!(item with crate::macro_::Macro::parse);
93
94 let output = match macro_.expand(attrs, format_ident!("function")) {
95 Ok(output) => output,
96 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
97 };
98
99 output.into()
100}
101
102#[proc_macro_attribute]
103#[doc(hidden)]
104pub fn module(
105 attrs: proc_macro::TokenStream,
106 item: proc_macro::TokenStream,
107) -> proc_macro::TokenStream {
108 let attrs = syn::parse_macro_input!(attrs with crate::module::ModuleAttrs::parse);
109 let module = syn::parse_macro_input!(item with crate::module::Module::parse);
110
111 let output = match module.expand(attrs) {
112 Ok(output) => output,
113 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
114 };
115
116 output.into()
117}
118
119#[proc_macro_attribute]
120#[doc(hidden)]
121pub fn attribute_macro(
122 attrs: proc_macro::TokenStream,
123 item: proc_macro::TokenStream,
124) -> proc_macro::TokenStream {
125 let attrs = syn::parse_macro_input!(attrs with crate::macro_::Config::parse);
126 let macro_ = syn::parse_macro_input!(item with crate::macro_::Macro::parse);
127
128 let output = match macro_.expand(attrs, format_ident!("attribute")) {
129 Ok(output) => output,
130 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
131 };
132
133 output.into()
134}
135
136#[proc_macro_derive(ToTokens, attributes(rune))]
137#[doc(hidden)]
138pub fn to_tokens(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
139 let derive = syn::parse_macro_input!(input as to_tokens::Derive);
140 Context::build(|cx| derive.expand(cx)).into()
141}
142
143#[proc_macro_derive(Parse, attributes(rune))]
144#[doc(hidden)]
145pub fn parse(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
146 let derive = syn::parse_macro_input!(input as parse::Derive);
147 Context::build(|cx| derive.expand(cx)).into()
148}
149
150#[proc_macro_derive(Spanned, attributes(rune))]
152pub fn spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
153 let derive = syn::parse_macro_input!(input as spanned::Derive);
154 Context::build(|cx| derive.expand(cx, false)).into()
155}
156
157#[proc_macro_derive(OptionSpanned, attributes(rune))]
158#[doc(hidden)]
159pub fn option_spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
160 let derive = syn::parse_macro_input!(input as spanned::Derive);
161 Context::build(|cx| derive.expand(cx, true)).into()
162}
163
164#[proc_macro_derive(Opaque, attributes(rune))]
165#[doc(hidden)]
166pub fn opaque(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
167 let derive = syn::parse_macro_input!(input as opaque::Derive);
168 Context::build(|cx| derive.expand(cx)).into()
169}
170
171#[proc_macro_derive(FromValue, attributes(rune))]
172#[doc(hidden)]
173pub fn from_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
174 let input = syn::parse_macro_input!(input as syn::DeriveInput);
175 Context::build(|cx| from_value::expand(cx, &input)).into()
176}
177
178#[proc_macro_derive(ToValue, attributes(rune))]
179#[doc(hidden)]
180pub fn to_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
181 let input = syn::parse_macro_input!(input as syn::DeriveInput);
182 Context::build(|cx| to_value::expand(cx, &input)).into()
183}
184
185#[proc_macro_derive(Any, attributes(rune))]
186#[doc(hidden)]
187pub fn any(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
188 let derive = syn::parse_macro_input!(input as any::Derive);
189
190 let stream = Context::build(|cx| {
191 let attr = cx.type_attrs(&derive.input.attrs);
192 let tokens = cx.tokens_with_module(attr.module.as_ref());
193 Ok(derive.into_any_builder(cx, &attr, &tokens)?.expand())
194 });
195
196 stream.into()
197}
198
199#[proc_macro_derive(ToConstValue, attributes(const_value))]
200#[doc(hidden)]
201pub fn const_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
202 let derive = syn::parse_macro_input!(input as const_value::Derive);
203 Context::build(|cx| Ok(derive.into_builder(cx)?.expand())).into()
204}
205
206#[proc_macro]
207#[doc(hidden)]
208pub fn hash(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
209 let args = syn::parse_macro_input!(input as self::hash::Arguments);
210
211 let stream = Context::build(|cx| {
212 let Tokens { hash, .. } = cx.tokens_with_module(None);
213 let value = args.build_type_hash(cx)?.into_inner();
214 Ok(::quote::quote!(#hash(#value)))
215 });
216
217 stream.into()
218}
219
220#[proc_macro]
221#[doc(hidden)]
222pub fn hash_in(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
223 let path_in::PathIn { in_crate, item, .. } =
224 syn::parse_macro_input!(input as path_in::PathIn<self::hash::Arguments>);
225
226 let stream = Context::build(|cx| {
227 let value = item.build_type_hash(cx)?.into_inner();
228 Ok(::quote::quote!(#in_crate::Hash(#value)))
229 });
230
231 stream.into()
232}
233
234#[proc_macro]
235#[doc(hidden)]
236pub fn item(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
237 let path = syn::parse_macro_input!(input as syn::Path);
238
239 let stream = match self::item::build_item(&path) {
240 Ok(hash) => {
241 ::quote::quote!(unsafe { rune::Item::from_bytes(&#hash) })
242 }
243 Err(error) => to_compile_errors([error]),
244 };
245
246 stream.into()
247}
248
249#[proc_macro]
250#[doc(hidden)]
251pub fn item_in(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
252 let path_in::PathIn { in_crate, item, .. } = syn::parse_macro_input!(input as path_in::PathIn);
253
254 let stream = match self::item::build_item(&item) {
255 Ok(hash) => {
256 ::quote::quote!(unsafe { #in_crate::Item::from_bytes(&#hash) })
257 }
258 Err(error) => to_compile_errors([error]),
259 };
260
261 stream.into()
262}
263
264#[proc_macro]
265#[doc(hidden)]
266pub fn binding(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
267 let derive = syn::parse_macro_input!(input as any::InternalCall);
268
269 let stream = Context::build_with_crate(|cx| {
270 let mut stream = TokenStream::default();
271 let tokens = cx.tokens_with_module(None);
272
273 for builder in derive.into_any_builders(cx, &tokens) {
274 stream.extend(builder.expand());
275 }
276
277 Ok(stream)
278 });
279
280 stream.into()
281}
282
283#[proc_macro_attribute]
284#[doc(hidden)]
285pub fn stable(
286 _attr: proc_macro::TokenStream,
287 item: proc_macro::TokenStream,
288) -> proc_macro::TokenStream {
289 item
290}
291
292#[proc_macro_attribute]
293#[doc(hidden)]
294pub fn unstable(
295 _attr: proc_macro::TokenStream,
296 item: proc_macro::TokenStream,
297) -> proc_macro::TokenStream {
298 item
299}
300
301#[proc_macro_derive(InstDisplay, attributes(inst_display))]
302#[doc(hidden)]
303pub fn inst_display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
304 let derive = syn::parse_macro_input!(input as inst_display::Derive);
305 derive.expand().unwrap_or_else(to_compile_errors).into()
306}
307
308fn add_trait_bounds(generics: &mut Generics, path: &Path) {
310 for ty in &mut generics.type_params_mut() {
311 ty.bounds.push(syn::TypeParamBound::Trait(syn::TraitBound {
312 paren_token: None,
313 modifier: syn::TraitBoundModifier::None,
314 lifetimes: None,
315 path: path.clone(),
316 }));
317 }
318}
319
320fn to_compile_errors<I>(errors: I) -> proc_macro2::TokenStream
321where
322 I: IntoIterator<Item = syn::Error>,
323{
324 let compile_errors = errors.into_iter().map(syn::Error::into_compile_error);
325 ::quote::quote!(#(#compile_errors)*)
326}