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
40pub 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
135pub(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
202pub(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 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 type_hash: Hash,
579 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 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}