rune_macros/
any.rs

1use std::collections::BTreeMap;
2
3use proc_macro2::TokenStream;
4use quote::{quote, quote_spanned, ToTokens};
5use rune_core::hash::Hash;
6use syn::punctuated::Punctuated;
7use syn::spanned::Spanned;
8use syn::Token;
9
10use crate::context::{Context, Generate, GenerateTarget, Tokens, TypeAttr};
11
12struct InternalItem {
13    attrs: Vec<syn::Attribute>,
14    #[allow(unused)]
15    impl_token: Token![impl],
16    params: Option<Params>,
17    item: syn::Path,
18    #[allow(unused)]
19    for_token: Token![for],
20    ty: syn::Type,
21}
22
23impl syn::parse::Parse for InternalItem {
24    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
25        Ok(Self {
26            attrs: syn::Attribute::parse_outer(input)?,
27            impl_token: input.parse()?,
28            params: if input.peek(Token![<]) {
29                Some(input.parse()?)
30            } else {
31                None
32            },
33            item: input.parse()?,
34            for_token: input.parse()?,
35            ty: input.parse()?,
36        })
37    }
38}
39
40/// An internal call to the macro.
41pub struct InternalCall {
42    items: Vec<(InternalItem, Option<Token![;]>)>,
43}
44
45impl syn::parse::Parse for InternalCall {
46    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
47        let mut items = Vec::new();
48
49        while !input.is_empty() {
50            let item = input.parse()?;
51            let semi = input.parse::<Option<Token![;]>>()?;
52            let done = semi.is_none();
53
54            items.push((item, semi));
55
56            if done {
57                break;
58            }
59        }
60
61        Ok(Self { items })
62    }
63}
64
65impl InternalCall {
66    pub(super) fn into_any_builders<'a>(
67        self,
68        cx: &Context,
69        attr: &'a TypeAttr,
70        tokens: &'a Tokens,
71    ) -> Vec<TypeBuilder<'a, syn::Type>> {
72        let mut output = Vec::new();
73
74        for (item, _) in self.items {
75            let type_item = match crate::item::build_item(&item.item) {
76                Ok(type_item) => type_item,
77                Err(error) => {
78                    cx.error(error);
79                    continue;
80                }
81            };
82
83            let mut any = None;
84            let mut type_of = None;
85            let mut attrs = Vec::new();
86
87            for attr in item.attrs {
88                if attr.path().is_ident("any") {
89                    any = Some(attr.path().span());
90                    continue;
91                }
92
93                if attr.path().is_ident("type_of") {
94                    type_of = Some(attr.path().span());
95                    continue;
96                }
97
98                attrs.push(attr);
99            }
100
101            let args = crate::hash::Arguments::new(item.item);
102
103            let Ok(type_hash) = args.build_type_hash(cx) else {
104                continue;
105            };
106
107            let kind = match (any, type_of) {
108                (Some(a), Some(..)) => {
109                    cx.error(syn::Error::new(a, "Cannot combine #[any] and #[type_of]"));
110                    continue;
111                }
112                (Some(..), _) => TypeKind::Any,
113                (_, Some(..)) => TypeKind::TypeOf,
114                (None, None) => TypeKind::Derive,
115            };
116
117            output.push(TypeBuilder {
118                attr,
119                ident: item.ty,
120                type_hash,
121                type_item,
122                installers: Vec::new(),
123                tokens,
124                generics: syn::Generics::default(),
125                attrs,
126                params: item.params,
127                kind,
128            });
129        }
130
131        output
132    }
133}
134
135/// An internal call to the macro.
136pub(super) struct Derive {
137    pub(super) input: syn::DeriveInput,
138}
139
140impl syn::parse::Parse for Derive {
141    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
142        Ok(Self {
143            input: input.parse()?,
144        })
145    }
146}
147
148impl Derive {
149    pub(super) fn into_any_builder<'a>(
150        self,
151        cx: &Context,
152        attr: &'a TypeAttr,
153        tokens: &'a Tokens,
154    ) -> Result<TypeBuilder<'a, syn::Ident>, ()> {
155        let mut installers = Vec::new();
156
157        let mut item = match &attr.item {
158            Some(item) => item.clone(),
159            None => syn::Path {
160                leading_colon: None,
161                segments: Punctuated::default(),
162            },
163        };
164
165        let name = match &attr.name {
166            Some(name) => name,
167            None => &self.input.ident,
168        };
169
170        item.segments.push(syn::PathSegment::from(name.clone()));
171
172        let args = crate::hash::Arguments::new(item);
173        let type_item = args.build_type_item(cx)?;
174        let type_hash = args.build_type_hash(cx)?;
175
176        expand_install_with(cx, &self.input, tokens, attr, &mut installers, &args)?;
177
178        if matches!(&self.input.data, syn::Data::Enum(..)) {
179            if let Some(span) = attr.constructor {
180                cx.error(syn::Error::new(
181                    span,
182                    "#[rune(constructor)] is not supported on enums, only its variants",
183                ));
184            }
185        }
186
187        Ok(TypeBuilder {
188            attr,
189            ident: self.input.ident,
190            type_hash,
191            type_item,
192            installers,
193            tokens,
194            generics: self.input.generics,
195            attrs: Vec::new(),
196            params: None,
197            kind: TypeKind::Derive,
198        })
199    }
200}
201
202/// Expannd the install into impl.
203pub(crate) fn expand_install_with(
204    cx: &Context,
205    input: &syn::DeriveInput,
206    tokens: &Tokens,
207    attr: &TypeAttr,
208    installers: &mut Vec<TokenStream>,
209    args: &crate::hash::Arguments,
210) -> Result<(), ()> {
211    let ident = &input.ident;
212
213    match &input.data {
214        syn::Data::Struct(st) => {
215            expand_struct_install_with(cx, installers, ident, st, tokens, attr)?;
216        }
217        syn::Data::Enum(en) => {
218            expand_enum_install_with(
219                cx,
220                installers,
221                ident,
222                en,
223                tokens,
224                attr,
225                &input.generics,
226                args,
227            )?;
228        }
229        syn::Data::Union(..) => {
230            cx.error(syn::Error::new_spanned(
231                input,
232                "#[derive(Any)]: Not supported on unions",
233            ));
234            return Err(());
235        }
236    }
237
238    if let Some(install_with) = &attr.install_with {
239        installers.push(quote_spanned! { input.span() =>
240            #install_with(module)?;
241        });
242    }
243
244    Ok(())
245}
246
247fn expand_struct_install_with(
248    cx: &Context,
249    installers: &mut Vec<TokenStream>,
250    ident: &syn::Ident,
251    st: &syn::DataStruct,
252    tokens: &Tokens,
253    attr: &TypeAttr,
254) -> Result<(), ()> {
255    for (n, field) in st.fields.iter().enumerate() {
256        let attrs = cx.field_attrs(&field.attrs);
257        let name;
258        let index;
259
260        let target = match &field.ident {
261            Some(ident) => {
262                name = syn::LitStr::new(&ident.to_string(), ident.span());
263
264                GenerateTarget::Named {
265                    field_ident: ident,
266                    field_name: &name,
267                }
268            }
269            None => {
270                index = syn::LitInt::new(&n.to_string(), field.span());
271
272                GenerateTarget::Numbered {
273                    field_index: &index,
274                }
275            }
276        };
277
278        let ty = &field.ty;
279
280        for protocol in &attrs.protocols {
281            installers.push((protocol.generate)(Generate {
282                tokens,
283                protocol,
284                attrs: &attrs,
285                field,
286                ty,
287                target,
288            }));
289        }
290    }
291
292    let mut docs = syn::ExprArray {
293        attrs: Vec::new(),
294        bracket_token: syn::token::Bracket::default(),
295        elems: Punctuated::default(),
296    };
297
298    for el in &attr.docs {
299        docs.elems.push(el.clone());
300    }
301
302    match &st.fields {
303        syn::Fields::Named(fields) => {
304            let constructor = attr
305                .constructor
306                .is_some()
307                .then(|| make_constructor(syn::parse_quote!(#ident), &fields.named));
308
309            let fields = fields.named.iter().flat_map(|f| {
310                let ident = f.ident.as_ref()?;
311                Some(syn::LitStr::new(&ident.to_string(), ident.span()))
312            });
313
314            installers.push(quote! {
315                module.type_meta::<Self>()?.make_named_struct(&[#(#fields,)*])?.static_docs(&#docs)?#constructor;
316            });
317        }
318        syn::Fields::Unnamed(fields) => {
319            let len = fields.unnamed.len();
320
321            installers.push(quote! {
322                module.type_meta::<Self>()?.make_unnamed_struct(#len)?.static_docs(&#docs)?;
323            });
324        }
325        syn::Fields::Unit => {
326            installers.push(quote! {
327                module.type_meta::<Self>()?.make_empty_struct()?.static_docs(&#docs)?;
328            });
329        }
330    }
331
332    Ok(())
333}
334
335fn expand_enum_install_with(
336    cx: &Context,
337    installers: &mut Vec<TokenStream>,
338    ident: &syn::Ident,
339    en: &syn::DataEnum,
340    tokens: &Tokens,
341    attr: &TypeAttr,
342    generics: &syn::Generics,
343    args: &crate::hash::Arguments,
344) -> Result<(), ()> {
345    let Tokens {
346        protocol,
347        runtime_error,
348        to_value,
349        vm_result,
350        vm_try,
351        any_t,
352        try_clone,
353        hash,
354        ..
355    } = tokens;
356
357    let (_, type_generics, _) = generics.split_for_impl();
358
359    let mut is_variant = Vec::new();
360    let mut variant_metas = Vec::new();
361    let mut variant_names = Vec::new();
362    let mut variants = Vec::new();
363
364    // Protocol::GET implementations per available field. Each implementation
365    // needs to match the enum to extract the appropriate field.
366    let mut field_fns = BTreeMap::<String, Vec<TokenStream>>::new();
367    let mut index_fns = BTreeMap::<usize, Vec<TokenStream>>::new();
368
369    for (variant_index, variant) in en.variants.iter().enumerate() {
370        let span = variant.fields.span();
371
372        let variant_attr = cx.variant_attr(&variant.attrs);
373
374        let mut variant_docs = syn::ExprArray {
375            attrs: Vec::new(),
376            bracket_token: syn::token::Bracket::default(),
377            elems: Punctuated::default(),
378        };
379
380        for el in &variant_attr.docs {
381            variant_docs.elems.push(el.clone());
382        }
383
384        let variant_ident = &variant.ident;
385        let variant_name = variant_ident.to_string();
386        variant_names.push(syn::LitStr::new(&variant_name, span));
387
388        let Ok(variant_hash) = args.build_type_hash_with(cx, &variant_name) else {
389            continue;
390        };
391
392        let variant_hash = variant_hash.into_inner();
393
394        is_variant.push(quote!((#ident::#variant_ident { .. }, #hash(#variant_hash)) => true));
395
396        match &variant.fields {
397            syn::Fields::Named(fields) => {
398                let mut field_names = Vec::new();
399
400                for f in &fields.named {
401                    let attrs = cx.field_attrs(&f.attrs);
402
403                    let Some(f_ident) = &f.ident else {
404                        cx.error(syn::Error::new_spanned(f, "Missing field name"));
405                        return Err(());
406                    };
407
408                    if attrs.field {
409                        let f_name = f_ident.to_string();
410                        let name = syn::LitStr::new(&f_name, f.span());
411                        field_names.push(name);
412
413                        let fields = field_fns.entry(f_name).or_default();
414
415                        let to_value = if attrs.copy {
416                            quote!(#vm_try!(#to_value::to_value(*#f_ident)))
417                        } else {
418                            quote!(#vm_try!(#to_value::to_value(#vm_try!(#try_clone::try_clone(#f_ident)))))
419                        };
420
421                        fields.push(quote!(#ident::#variant_ident { #f_ident, .. } => #vm_result::Ok(#to_value)));
422                    }
423                }
424
425                let constructor = variant_attr.constructor.is_some().then(|| {
426                    make_constructor(syn::parse_quote!(#ident::#variant_ident), &fields.named)
427                });
428
429                variant_metas.push(quote! {
430                    enum_.variant_mut(#variant_index)?.make_named(&[#(#field_names),*])?.static_docs(&#variant_docs)?#constructor
431                });
432
433                variants.push((None, variant_attr));
434            }
435            syn::Fields::Unnamed(fields) => {
436                let mut fields_len = 0usize;
437
438                for (n, field) in fields.unnamed.iter().enumerate() {
439                    let span = field.span();
440                    let attrs = cx.field_attrs(&field.attrs);
441
442                    if attrs.field {
443                        fields_len += 1;
444                        let fields = index_fns.entry(n).or_default();
445                        let n = syn::LitInt::new(&n.to_string(), span);
446
447                        let to_value = if attrs.copy {
448                            quote!(#vm_try!(#to_value::to_value(*value)))
449                        } else {
450                            quote!(#vm_try!(#to_value::to_value(#vm_try!(#try_clone::try_clone(value)))))
451                        };
452
453                        fields.push(quote!(#ident::#variant_ident { #n: value, .. } => #vm_result::Ok(#to_value)));
454                    }
455                }
456
457                variant_metas.push(quote! {
458                    enum_.variant_mut(#variant_index)?.make_unnamed(#fields_len)?.static_docs(&#variant_docs)?
459                });
460
461                if variant_attr.constructor.is_some() && fields_len != fields.unnamed.len() {
462                    cx.error(syn::Error::new_spanned(fields, "#[rune(constructor)] can only be used if all fields are marked with #[rune(get)"));
463                }
464
465                let constructor = variant_attr
466                    .constructor
467                    .is_some()
468                    .then(|| quote!(#ident #type_generics :: #variant_ident));
469
470                variants.push((constructor, variant_attr));
471            }
472            syn::Fields::Unit => {
473                variant_metas.push(quote! {
474                    enum_.variant_mut(#variant_index)?.make_empty()?.static_docs(&#variant_docs)?
475                });
476
477                let constructor = if variant_attr.constructor.is_some() {
478                    Some(quote!(|| #ident #type_generics :: #variant_ident))
479                } else {
480                    None
481                };
482
483                variants.push((constructor, variant_attr));
484            }
485        }
486    }
487
488    let is_variant = quote! {
489        module.associated_function(&#protocol::IS_VARIANT, |this: &Self, hash: #hash| {
490            match (this, hash) {
491                #(#is_variant,)*
492                _ => false,
493            }
494        })?;
495    };
496
497    installers.push(is_variant);
498
499    for (field, matches) in field_fns {
500        installers.push(quote! {
501            module.field_function(&#protocol::GET, #field, |this: &Self| {
502                match this {
503                    #(#matches,)*
504                    _ => return #vm_result::err(
505                        #runtime_error::__rune_macros__unsupported_object_field_get(
506                            <Self as #any_t>::ANY_TYPE_INFO
507                        )
508                    ),
509                }
510            })?;
511        });
512    }
513
514    for (index, matches) in index_fns {
515        installers.push(quote! {
516            module.index_function(&#protocol::GET, #index, |this: &Self| {
517                match this {
518                    #(#matches,)*
519                    _ => return #vm_result::err(
520                        #runtime_error::__rune_macros__unsupported_tuple_index_get(
521                            <Self as #any_t>::ANY_TYPE_INFO,
522                            #index
523                        )
524                    ),
525                }
526            })?;
527        });
528    }
529
530    let mut docs = syn::ExprArray {
531        attrs: Vec::new(),
532        bracket_token: syn::token::Bracket::default(),
533        elems: Punctuated::default(),
534    };
535
536    for el in &attr.docs {
537        docs.elems.push(el.clone());
538    }
539
540    let enum_meta = quote! {
541        let mut enum_ = module.type_meta::<Self>()?.make_enum(&[#(#variant_names,)*])?.static_docs(&#docs)?;
542        #(#variant_metas;)*
543    };
544
545    installers.push(enum_meta);
546
547    for (index, (constructor, attr)) in variants.iter().enumerate() {
548        let mut docs = syn::ExprArray {
549            attrs: Vec::new(),
550            bracket_token: syn::token::Bracket::default(),
551            elems: Punctuated::default(),
552        };
553
554        for el in &attr.docs {
555            docs.elems.push(el.clone());
556        }
557
558        let constructor = constructor.as_ref().map(|c| quote!(.constructor(#c)?));
559
560        installers.push(quote! {
561                module.variant_meta::<Self>(#index)?.static_docs(&#docs)?#constructor;
562        });
563    }
564
565    Ok(())
566}
567
568enum TypeKind {
569    Any,
570    TypeOf,
571    Derive,
572}
573
574pub struct TypeBuilder<'a, T> {
575    attr: &'a TypeAttr,
576    ident: T,
577    /// Hash of the type.
578    type_hash: Hash,
579    /// Bytes corresponding to the item array.
580    type_item: syn::ExprArray,
581    installers: Vec<TokenStream>,
582    tokens: &'a Tokens,
583    generics: syn::Generics,
584    attrs: Vec<syn::Attribute>,
585    params: Option<Params>,
586    kind: TypeKind,
587}
588
589impl<T> TypeBuilder<'_, T>
590where
591    T: ToTokens,
592{
593    /// Expand the necessary implementation details for `Any`.
594    pub(super) fn expand(self) -> TokenStream {
595        match self.kind {
596            TypeKind::Derive => self.expand_derive(),
597            TypeKind::Any => self.expand_any(),
598            TypeKind::TypeOf => self.expand_type_of(),
599        }
600    }
601
602    pub(super) fn expand_derive(self) -> TokenStream {
603        let TypeBuilder {
604            attr,
605            ident,
606            type_hash,
607            type_item,
608            installers,
609            tokens,
610            generics,
611            attrs,
612            ..
613        } = self;
614
615        let Tokens {
616            alloc,
617            any_t,
618            any_marker_t,
619            context_error,
620            fmt,
621            hash,
622            install_with,
623            item,
624            maybe_type_of,
625            meta,
626            module,
627            named,
628            non_null,
629            raw_value_guard,
630            result,
631            any_type_info,
632            type_hash_t,
633            type_of,
634            unsafe_to_mut,
635            unsafe_to_ref,
636            unsafe_to_value,
637            value_mut_guard,
638            value_ref_guard,
639            value,
640            write,
641            runtime_error,
642            ..
643        } = tokens;
644
645        let empty;
646        let mut current;
647        let generic_names;
648
649        let (impl_generics, type_generics, where_clause) = match &attr.impl_params {
650            Some(params) => {
651                empty = syn::Generics::default();
652                current = syn::Generics::default();
653
654                for p in params {
655                    current.params.push(syn::GenericParam::Type(p.clone()));
656                }
657
658                let (impl_generics, _, where_clause) = empty.split_for_impl();
659                let (_, type_generics, _) = current.split_for_impl();
660                generic_names = Vec::new();
661                (impl_generics, type_generics, where_clause)
662            }
663            None => {
664                current = generics;
665                generic_names = current.type_params().map(|v| &v.ident).collect::<Vec<_>>();
666                current.split_for_impl()
667            }
668        };
669
670        let named_rest = if let [first_name, remainder @ ..] = &generic_names[..] {
671            Some(quote! {
672                #write!(f, "<")?;
673                #first_name::full_name(f)?;
674                #(
675                    #write!(f, ", ")?;
676                    #remainder::full_name(f)?;
677                )*
678                #write!(f, ">")?;
679            })
680        } else {
681            None
682        };
683
684        let impl_named = quote! {
685            #[automatically_derived]
686            #(#attrs)*
687            impl #impl_generics #named for #ident #type_generics #where_clause {
688                const ITEM: &'static #item = unsafe { #item::from_bytes(&#type_item) };
689
690                #[inline]
691                fn full_name(f: &mut #fmt::Formatter<'_>) -> #fmt::Result {
692                    #fmt::Display::fmt(Self::ITEM, f)?;
693                    #named_rest
694                    #result::Ok(())
695                }
696            }
697        };
698
699        let install_with = quote! {
700            #[automatically_derived]
701            #(#attrs)*
702            impl #impl_generics #install_with for #ident #type_generics #where_clause {
703                fn install_with(#[allow(unused)] module: &mut #module) -> core::result::Result<(), #context_error> {
704                    #(#installers)*
705                    Ok(())
706                }
707            }
708        };
709
710        let type_hash = type_hash.into_inner();
711
712        let make_hash = if !generic_names.is_empty() {
713            quote!(#hash::new_with_type_parameters(#type_hash, #hash::parameters([#(<#generic_names as #type_hash_t>::HASH),*])))
714        } else {
715            quote!(#hash::new(#type_hash))
716        };
717
718        let type_parameters =
719            quote!(#hash::parameters([#(<#generic_names as #type_hash_t>::HASH),*]));
720
721        let to_value_impl = quote! {
722            #[automatically_derived]
723            #(#attrs)*
724            impl #impl_generics #unsafe_to_ref for #ident #type_generics #where_clause {
725                type Guard = #raw_value_guard;
726
727                #[inline]
728                unsafe fn unsafe_to_ref<'a>(value: #value) -> #result<(&'a Self, Self::Guard), #runtime_error> {
729                    let (value, guard) = #value::into_any_ref_ptr(value)?;
730                    #result::Ok((#non_null::as_ref(&value), guard))
731                }
732            }
733
734            #[automatically_derived]
735            #(#attrs)*
736            impl #impl_generics #unsafe_to_mut for #ident #type_generics #where_clause {
737                type Guard = #raw_value_guard;
738
739                #[inline]
740                unsafe fn unsafe_to_mut<'a>(value: #value) -> #result<(&'a mut Self, Self::Guard), #runtime_error> {
741                    let (mut value, guard) = #value::into_any_mut_ptr(value)?;
742                    #result::Ok((#non_null::as_mut(&mut value), guard))
743                }
744            }
745
746            #[automatically_derived]
747            #(#attrs)*
748            impl #impl_generics #unsafe_to_value for &#ident #type_generics #where_clause {
749                type Guard = #value_ref_guard;
750
751                #[inline]
752                unsafe fn unsafe_to_value(self) -> #result<(#value, Self::Guard), #runtime_error> {
753                    let (shared, guard) = #value::from_ref(self)?;
754                    #result::Ok((shared, guard))
755                }
756            }
757
758            #[automatically_derived]
759            #(#attrs)*
760            impl #impl_generics #unsafe_to_value for &mut #ident #type_generics #where_clause {
761                type Guard = #value_mut_guard;
762
763                #[inline]
764                unsafe fn unsafe_to_value(self) -> #result<(#value, Self::Guard), #runtime_error> {
765                    let (shared, guard) = #value::from_mut(self)?;
766                    #result::Ok((shared, guard))
767                }
768            }
769        };
770
771        let impl_type_of = quote! {
772            #[automatically_derived]
773            #(#attrs)*
774            impl #impl_generics #type_hash_t for #ident #type_generics #where_clause {
775                const HASH: #hash = #make_hash;
776            }
777
778            #[automatically_derived]
779            #(#attrs)*
780            impl #impl_generics #type_of for #ident #type_generics #where_clause {
781                const PARAMETERS: #hash = #type_parameters;
782                const STATIC_TYPE_INFO: #any_type_info = <Self as #any_t>::ANY_TYPE_INFO;
783            }
784
785            #[automatically_derived]
786            #(#attrs)*
787            impl #impl_generics #maybe_type_of for #ident #type_generics #where_clause {
788                #[inline]
789                fn maybe_type_of() -> #alloc::Result<#meta::DocType> {
790                    #meta::DocType::with_generics(
791                        <Self as #type_hash_t>::HASH,
792                        [#(<#generic_names as #maybe_type_of>::maybe_type_of()?),*]
793                    )
794                }
795            }
796        };
797
798        let impl_any = quote! {
799            #[automatically_derived]
800            #(#attrs)*
801            impl #impl_generics #any_t for #ident #type_generics #where_clause {
802            }
803        };
804
805        let impl_non_generic = quote! {
806            #[automatically_derived]
807            #(#attrs)*
808            impl #impl_generics #any_marker_t for #ident #type_generics #where_clause {
809            }
810        };
811
812        quote! {
813            #install_with
814            #impl_named
815            #to_value_impl
816            #impl_type_of
817            #impl_any
818            #impl_non_generic
819        }
820    }
821
822    pub(super) fn expand_any(self) -> TokenStream {
823        let TypeBuilder {
824            ident,
825            type_item,
826            installers,
827            tokens,
828            generics,
829            attrs,
830            ..
831        } = self;
832
833        let Tokens {
834            any_t,
835            context_error,
836            fmt,
837            install_with,
838            item,
839            module,
840            named,
841            non_null,
842            raw_value_guard,
843            result,
844            unsafe_to_mut,
845            unsafe_to_ref,
846            unsafe_to_value,
847            value_mut_guard,
848            value_ref_guard,
849            value,
850            write,
851            runtime_error,
852            ..
853        } = tokens;
854
855        let generic_names = generics.type_params().map(|v| &v.ident).collect::<Vec<_>>();
856        let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
857
858        let named_rest = if let [first_name, remainder @ ..] = &generic_names[..] {
859            Some(quote! {
860                #write!(f, "<")?;
861                #first_name::full_name(f)?;
862                #(
863                    #write!(f, ", ")?;
864                    #remainder::full_name(f)?;
865                )*
866                #write!(f, ">")?;
867            })
868        } else {
869            None
870        };
871
872        let impl_named = quote! {
873            #[automatically_derived]
874            #(#attrs)*
875            impl #impl_generics #named for #ident #type_generics #where_clause {
876                const ITEM: &'static #item = unsafe { #item::from_bytes(&#type_item) };
877
878                #[inline]
879                fn full_name(f: &mut #fmt::Formatter<'_>) -> #fmt::Result {
880                    #fmt::Display::fmt(Self::ITEM, f)?;
881                    #named_rest
882                    #result::Ok(())
883                }
884            }
885        };
886
887        let install_with = quote! {
888            #[automatically_derived]
889            #(#attrs)*
890            impl #impl_generics #install_with for #ident #type_generics #where_clause {
891                fn install_with(#[allow(unused)] module: &mut #module) -> core::result::Result<(), #context_error> {
892                    #(#installers)*
893                    Ok(())
894                }
895            }
896        };
897
898        let to_value_impl = quote! {
899            #[automatically_derived]
900            #(#attrs)*
901            impl #impl_generics #unsafe_to_ref for #ident #type_generics #where_clause {
902                type Guard = #raw_value_guard;
903
904                #[inline]
905                unsafe fn unsafe_to_ref<'a>(value: #value) -> #result<(&'a Self, Self::Guard), #runtime_error> {
906                    let (value, guard) = #value::into_any_ref_ptr(value)?;
907                    #result::Ok((#non_null::as_ref(&value), guard))
908                }
909            }
910
911            #[automatically_derived]
912            #(#attrs)*
913            impl #impl_generics #unsafe_to_mut for #ident #type_generics #where_clause {
914                type Guard = #raw_value_guard;
915
916                #[inline]
917                unsafe fn unsafe_to_mut<'a>(value: #value) -> #result<(&'a mut Self, Self::Guard), #runtime_error> {
918                    let (mut value, guard) = #value::into_any_mut_ptr(value)?;
919                    #result::Ok((#non_null::as_mut(&mut value), guard))
920                }
921            }
922
923            #[automatically_derived]
924            #(#attrs)*
925            impl #impl_generics #unsafe_to_value for &#ident #type_generics #where_clause {
926                type Guard = #value_ref_guard;
927
928                #[inline]
929                unsafe fn unsafe_to_value(self) -> #result<(#value, Self::Guard), #runtime_error> {
930                    let (shared, guard) = #value::from_ref(self)?;
931                    #result::Ok((shared, guard))
932                }
933            }
934
935            #[automatically_derived]
936            #(#attrs)*
937            impl #impl_generics #unsafe_to_value for &mut #ident #type_generics #where_clause {
938                type Guard = #value_mut_guard;
939
940                #[inline]
941                unsafe fn unsafe_to_value(self) -> #result<(#value, Self::Guard), #runtime_error> {
942                    let (shared, guard) = #value::from_mut(self)?;
943                    #result::Ok((shared, guard))
944                }
945            }
946        };
947
948        let impl_any = quote! {
949            #[automatically_derived]
950            #(#attrs)*
951            impl #impl_generics #any_t for #ident #type_generics #where_clause {
952            }
953        };
954
955        quote! {
956            #install_with
957            #impl_named
958            #to_value_impl
959            #impl_any
960        }
961    }
962
963    pub(super) fn expand_type_of(self) -> TokenStream {
964        let TypeBuilder {
965            ident,
966            type_item,
967            tokens,
968            attrs,
969            params,
970            type_hash,
971            ..
972        } = self;
973
974        let Tokens {
975            type_hash_t,
976            hash,
977            maybe_type_of,
978            any_type_info,
979            fmt,
980            meta,
981            item,
982            type_of,
983            alloc,
984            ..
985        } = tokens;
986
987        let p = params
988            .as_ref()
989            .into_iter()
990            .flat_map(|p| p.params.iter())
991            .collect::<Vec<_>>();
992
993        let type_hash = type_hash.into_inner();
994        let make_hash = quote!(#hash::new(#type_hash));
995
996        quote! {
997            #[automatically_derived]
998            #(#attrs)*
999            impl #params #type_hash_t for #ident {
1000                const HASH: #hash = #make_hash;
1001            }
1002
1003            #[automatically_derived]
1004            #(#attrs)*
1005            impl #params #type_of for #ident
1006            where
1007                #(#p: #maybe_type_of,)*
1008            {
1009                const STATIC_TYPE_INFO: #any_type_info = #any_type_info::new(
1010                    {
1011                        fn full_name(f: &mut #fmt::Formatter<'_>) -> #fmt::Result {
1012                            write!(f, "{}", unsafe { #item::from_bytes(&#type_item) })
1013                        }
1014
1015                        full_name
1016                    },
1017                    <Self as #type_hash_t>::HASH,
1018                );
1019            }
1020
1021            #[automatically_derived]
1022            #(#attrs)*
1023            impl #params #maybe_type_of for #ident
1024            where
1025                #(#p: #maybe_type_of,)*
1026            {
1027                #[inline]
1028                fn maybe_type_of() -> #alloc::Result<#meta::DocType> {
1029                    Ok(#meta::DocType::new(<Self as #type_hash_t>::HASH))
1030                }
1031            }
1032        }
1033    }
1034}
1035
1036struct Params {
1037    lt_token: Token![<],
1038    params: Punctuated<syn::Ident, Token![,]>,
1039    gt_token: Token![>],
1040}
1041
1042impl syn::parse::Parse for Params {
1043    #[inline]
1044    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
1045        let lt_token: Token![<] = input.parse()?;
1046
1047        let mut params = Punctuated::new();
1048
1049        loop {
1050            if input.peek(Token![>]) {
1051                break;
1052            }
1053
1054            params.push_value(input.parse()?);
1055
1056            if input.peek(Token![>]) {
1057                break;
1058            }
1059
1060            params.push_punct(input.parse()?);
1061        }
1062
1063        Ok(Self {
1064            lt_token,
1065            params,
1066            gt_token: input.parse()?,
1067        })
1068    }
1069}
1070
1071impl ToTokens for Params {
1072    #[inline]
1073    fn to_tokens(&self, tokens: &mut TokenStream) {
1074        self.lt_token.to_tokens(tokens);
1075        self.params.to_tokens(tokens);
1076        self.gt_token.to_tokens(tokens);
1077    }
1078}
1079
1080fn make_constructor(path: syn::Path, named: &Punctuated<syn::Field, Token![,]>) -> impl ToTokens {
1081    let args = named.iter().flat_map(|f| {
1082        let ident = f.ident.as_ref()?;
1083        let typ = &f.ty;
1084        Some(quote!(#ident: #typ))
1085    });
1086
1087    let field_names = named.iter().flat_map(|f| f.ident.as_ref());
1088
1089    quote! {
1090        .constructor(|#(#args),*| {
1091            #path {
1092                #(#field_names),*
1093            }
1094        })?
1095    }
1096}