rune_macros/
to_tokens.rs

1use crate::add_trait_bounds;
2use crate::context::{Context, Tokens};
3use proc_macro2::TokenStream;
4use quote::{quote, quote_spanned};
5use syn::spanned::Spanned as _;
6
7/// Derive implementation of the ToTokens macro.
8pub struct Derive {
9    input: syn::DeriveInput,
10}
11
12impl syn::parse::Parse for Derive {
13    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
14        Ok(Self {
15            input: input.parse()?,
16        })
17    }
18}
19
20impl Derive {
21    pub(super) fn expand(self, cx: &Context) -> Result<TokenStream, ()> {
22        let tokens = cx.tokens_with_module(None);
23
24        let mut expander = Expander { cx, tokens };
25
26        match &self.input.data {
27            syn::Data::Struct(st) => {
28                if let Ok(stream) = expander.expand_struct(&self.input, st) {
29                    return Ok(stream);
30                }
31            }
32            syn::Data::Enum(en) => {
33                if let Ok(stream) = expander.expand_enum(&self.input, en) {
34                    return Ok(stream);
35                }
36            }
37            syn::Data::Union(un) => {
38                expander.cx.error(syn::Error::new_spanned(
39                    un.union_token,
40                    "not supported on unions",
41                ));
42            }
43        }
44
45        Err(())
46    }
47}
48
49struct Expander<'cx> {
50    cx: &'cx Context,
51    tokens: Tokens,
52}
53
54impl Expander<'_> {
55    /// Expand on a struct.
56    fn expand_struct(
57        &mut self,
58        input: &syn::DeriveInput,
59        st: &syn::DataStruct,
60    ) -> Result<TokenStream, ()> {
61        _ = self.cx.type_attrs(&input.attrs);
62        self.expand_struct_fields(input, &st.fields)
63    }
64
65    /// Expand on a struct.
66    fn expand_enum(
67        &mut self,
68        input: &syn::DeriveInput,
69        st: &syn::DataEnum,
70    ) -> Result<TokenStream, ()> {
71        _ = self.cx.type_attrs(&input.attrs);
72
73        let mut impl_into_tokens = Vec::new();
74
75        for variant in &st.variants {
76            let expanded = self.expand_variant_fields(variant, &variant.fields)?;
77            impl_into_tokens.push(expanded);
78        }
79
80        let ident = &input.ident;
81        let Tokens {
82            to_tokens,
83            macro_context,
84            token_stream,
85            alloc,
86            ..
87        } = &self.tokens;
88
89        let mut generics = input.generics.clone();
90
91        add_trait_bounds(&mut generics, to_tokens);
92
93        let (impl_generics, type_generics, where_generics) = generics.split_for_impl();
94
95        Ok(quote! {
96            #[automatically_derived]
97            impl #impl_generics #to_tokens for #ident #type_generics #where_generics {
98                fn to_tokens(&self, context: &mut #macro_context, stream: &mut #token_stream) -> #alloc::Result<()> {
99                    match self {
100                        #(#impl_into_tokens),*
101                    }
102
103                    Ok(())
104                }
105            }
106        })
107    }
108
109    /// Expand field decoding.
110    fn expand_struct_fields(
111        &mut self,
112        input: &syn::DeriveInput,
113        fields: &syn::Fields,
114    ) -> Result<TokenStream, ()> {
115        match fields {
116            syn::Fields::Named(named) => self.expand_struct_named(input, named),
117            syn::Fields::Unnamed(..) => {
118                self.cx.error(syn::Error::new_spanned(
119                    fields,
120                    "tuple structs are not supported",
121                ));
122                Err(())
123            }
124            syn::Fields::Unit => {
125                self.cx.error(syn::Error::new_spanned(
126                    fields,
127                    "unit structs are not supported",
128                ));
129                Err(())
130            }
131        }
132    }
133
134    /// Expand variant ast.
135    fn expand_variant_fields(
136        &mut self,
137        variant: &syn::Variant,
138        fields: &syn::Fields,
139    ) -> Result<TokenStream, ()> {
140        match fields {
141            syn::Fields::Named(named) => self.expand_variant_named(variant, named),
142            syn::Fields::Unnamed(unnamed) => self.expand_variant_unnamed(variant, unnamed),
143            syn::Fields::Unit => Ok(self.expand_variant_unit(variant)),
144        }
145    }
146
147    /// Expand named fields.
148    fn expand_struct_named(
149        &mut self,
150        input: &syn::DeriveInput,
151        named: &syn::FieldsNamed,
152    ) -> Result<TokenStream, ()> {
153        let mut fields = Vec::new();
154
155        let Tokens {
156            to_tokens,
157            macro_context,
158            token_stream,
159            alloc,
160            ..
161        } = &self.tokens;
162
163        for field in &named.named {
164            let ident = self.cx.field_ident(field)?;
165            let attrs = self.cx.field_attrs(&field.attrs);
166
167            if attrs.skip() {
168                continue;
169            }
170
171            fields.push(quote! { #to_tokens::to_tokens(&self.#ident, context, stream)? })
172        }
173
174        let ident = &input.ident;
175
176        let mut generics = input.generics.clone();
177
178        add_trait_bounds(&mut generics, to_tokens);
179
180        let (impl_generics, type_generics, where_generics) = generics.split_for_impl();
181
182        let into_tokens_impl = quote_spanned! { named.span() =>
183            #[automatically_derived]
184            impl #impl_generics #to_tokens for #ident #type_generics #where_generics {
185                fn to_tokens(&self, context: &mut #macro_context, stream: &mut #token_stream) -> #alloc::Result<()> {
186                    #(#fields;)*
187                    Ok(())
188                }
189            }
190        };
191
192        Ok(quote_spanned! { named.span() =>
193            #into_tokens_impl
194        })
195    }
196
197    /// Expand named variant fields.
198    fn expand_variant_named(
199        &mut self,
200        variant: &syn::Variant,
201        named: &syn::FieldsNamed,
202    ) -> Result<TokenStream, ()> {
203        let mut fields = Vec::new();
204        let mut idents = Vec::new();
205
206        let Tokens { to_tokens, .. } = &self.tokens;
207
208        for field in &named.named {
209            let ident = self.cx.field_ident(field)?;
210            let attrs = self.cx.field_attrs(&field.attrs);
211            idents.push(ident);
212
213            if attrs.skip() {
214                continue;
215            }
216
217            fields.push(quote! { #to_tokens::to_tokens(&#ident, context, stream)? })
218        }
219
220        let ident = &variant.ident;
221
222        Ok(quote! {
223            Self::#ident { #(#idents,)* } => { #(#fields;)* }
224        })
225    }
226
227    /// Expand named variant fields.
228    fn expand_variant_unnamed(
229        &mut self,
230        variant: &syn::Variant,
231        named: &syn::FieldsUnnamed,
232    ) -> Result<TokenStream, ()> {
233        let mut field_into_tokens = Vec::new();
234        let mut idents = Vec::new();
235
236        let Tokens { to_tokens, .. } = &self.tokens;
237
238        for (n, field) in named.unnamed.iter().enumerate() {
239            let ident = syn::Ident::new(&format!("f{}", n), field.span());
240            let attrs = self.cx.field_attrs(&field.attrs);
241
242            idents.push(ident.clone());
243
244            if attrs.skip() {
245                continue;
246            }
247
248            field_into_tokens.push(quote! { #to_tokens::to_tokens(#ident, context, stream)? })
249        }
250
251        let ident = &variant.ident;
252
253        Ok(quote! {
254            Self::#ident(#(#idents,)*) => { #(#field_into_tokens;)* }
255        })
256    }
257
258    /// Expand unit variant.
259    fn expand_variant_unit(&mut self, variant: &syn::Variant) -> TokenStream {
260        let ident = &variant.ident;
261
262        quote_spanned! { variant.span() =>
263            Self::#ident => ()
264        }
265    }
266}