1 use proc_macro2::{Span, TokenStream};
2 use quote::{format_ident, quote};
3 use std::collections::HashSet;
4 use std::fmt;
5 use syn::parse::{Parse, ParseStream};
6 use syn::punctuated::Punctuated;
7 use syn::{braced, parse_quote, Data, DeriveInput, Error, Ident, Result, Token};
8 use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9 
10 mod kw {
11     syn::custom_keyword!(record);
12     syn::custom_keyword!(variant);
13     syn::custom_keyword!(flags);
14     syn::custom_keyword!(name);
15     syn::custom_keyword!(wasmtime_crate);
16 }
17 
18 #[derive(Debug, Copy, Clone)]
19 pub enum VariantStyle {
20     Variant,
21     Enum,
22 }
23 
24 impl fmt::Display for VariantStyle {
25     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26         f.write_str(match self {
27             Self::Variant => "variant",
28             Self::Enum => "enum",
29         })
30     }
31 }
32 
33 #[derive(Debug, Copy, Clone)]
34 enum Style {
35     Record,
36     Variant(VariantStyle),
37 }
38 
39 #[derive(Debug, Clone)]
40 enum ComponentAttr {
41     Style(Style),
42     WasmtimeCrate(syn::Path),
43 }
44 
45 impl Parse for ComponentAttr {
46     fn parse(input: ParseStream) -> Result<Self> {
47         let lookahead = input.lookahead1();
48         if lookahead.peek(kw::record) {
49             input.parse::<kw::record>()?;
50             Ok(ComponentAttr::Style(Style::Record))
51         } else if lookahead.peek(kw::variant) {
52             input.parse::<kw::variant>()?;
53             Ok(ComponentAttr::Style(Style::Variant(VariantStyle::Variant)))
54         } else if lookahead.peek(Token![enum]) {
55             input.parse::<Token![enum]>()?;
56             Ok(ComponentAttr::Style(Style::Variant(VariantStyle::Enum)))
57         } else if lookahead.peek(kw::wasmtime_crate) {
58             input.parse::<kw::wasmtime_crate>()?;
59             input.parse::<Token![=]>()?;
60             Ok(ComponentAttr::WasmtimeCrate(input.parse()?))
61         } else if input.peek(kw::flags) {
62             Err(input.error(
63                 "`flags` not allowed here; \
64                  use `wasmtime::component::flags!` macro to define `flags` types",
65             ))
66         } else {
67             Err(lookahead.error())
68         }
69     }
70 }
71 
72 fn find_rename(attributes: &[syn::Attribute]) -> Result<Option<syn::LitStr>> {
73     let mut name = None;
74 
75     for attribute in attributes {
76         if !attribute.path().is_ident("component") {
77             continue;
78         }
79         let name_literal = attribute.parse_args_with(|parser: ParseStream<'_>| {
80             parser.parse::<kw::name>()?;
81             parser.parse::<Token![=]>()?;
82             parser.parse::<syn::LitStr>()
83         })?;
84 
85         if name.is_some() {
86             return Err(Error::new_spanned(
87                 attribute,
88                 "duplicate field rename attribute",
89             ));
90         }
91 
92         name = Some(name_literal);
93     }
94 
95     Ok(name)
96 }
97 
98 fn add_trait_bounds(generics: &syn::Generics, bound: syn::TypeParamBound) -> syn::Generics {
99     let mut generics = generics.clone();
100     for param in &mut generics.params {
101         if let syn::GenericParam::Type(ref mut type_param) = *param {
102             type_param.bounds.push(bound.clone());
103         }
104     }
105     generics
106 }
107 
108 pub struct VariantCase<'a> {
109     attrs: &'a [syn::Attribute],
110     ident: &'a syn::Ident,
111     ty: Option<&'a syn::Type>,
112 }
113 
114 pub trait Expander {
115     fn expand_record(
116         &self,
117         name: &syn::Ident,
118         generics: &syn::Generics,
119         fields: &[&syn::Field],
120         wasmtime_crate: &syn::Path,
121     ) -> Result<TokenStream>;
122 
123     fn expand_variant(
124         &self,
125         name: &syn::Ident,
126         generics: &syn::Generics,
127         discriminant_size: DiscriminantSize,
128         cases: &[VariantCase],
129         style: VariantStyle,
130         wasmtime_crate: &syn::Path,
131     ) -> Result<TokenStream>;
132 }
133 
134 pub fn expand(expander: &dyn Expander, input: &DeriveInput) -> Result<TokenStream> {
135     let mut wasmtime_crate = None;
136     let mut style = None;
137 
138     for attribute in &input.attrs {
139         if !attribute.path().is_ident("component") {
140             continue;
141         }
142         match attribute.parse_args()? {
143             ComponentAttr::WasmtimeCrate(c) => wasmtime_crate = Some(c),
144             ComponentAttr::Style(attr_style) => {
145                 if style.is_some() {
146                     return Err(Error::new_spanned(
147                         attribute,
148                         "duplicate `component` attribute",
149                     ));
150                 }
151                 style = Some(attr_style);
152             }
153         }
154     }
155 
156     let style = style.ok_or_else(|| Error::new_spanned(input, "missing `component` attribute"))?;
157     let wasmtime_crate = wasmtime_crate.unwrap_or_else(default_wasmtime_crate);
158     match style {
159         Style::Record => expand_record(expander, input, &wasmtime_crate),
160         Style::Variant(style) => expand_variant(expander, input, style, &wasmtime_crate),
161     }
162 }
163 
164 fn default_wasmtime_crate() -> syn::Path {
165     Ident::new("wasmtime", Span::call_site()).into()
166 }
167 
168 fn expand_record(
169     expander: &dyn Expander,
170     input: &DeriveInput,
171     wasmtime_crate: &syn::Path,
172 ) -> Result<TokenStream> {
173     let name = &input.ident;
174 
175     let body = if let Data::Struct(body) = &input.data {
176         body
177     } else {
178         return Err(Error::new(
179             name.span(),
180             "`record` component types can only be derived for Rust `struct`s",
181         ));
182     };
183 
184     match &body.fields {
185         syn::Fields::Named(fields) => expander.expand_record(
186             &input.ident,
187             &input.generics,
188             &fields.named.iter().collect::<Vec<_>>(),
189             wasmtime_crate,
190         ),
191 
192         syn::Fields::Unnamed(_) | syn::Fields::Unit => Err(Error::new(
193             name.span(),
194             "`record` component types can only be derived for `struct`s with named fields",
195         )),
196     }
197 }
198 
199 fn expand_variant(
200     expander: &dyn Expander,
201     input: &DeriveInput,
202     style: VariantStyle,
203     wasmtime_crate: &syn::Path,
204 ) -> Result<TokenStream> {
205     let name = &input.ident;
206 
207     let body = if let Data::Enum(body) = &input.data {
208         body
209     } else {
210         return Err(Error::new(
211             name.span(),
212             format!("`{style}` component types can only be derived for Rust `enum`s"),
213         ));
214     };
215 
216     if body.variants.is_empty() {
217         return Err(Error::new(
218             name.span(),
219             format!("`{style}` component types can only be derived for Rust `enum`s with at least one variant"),
220         ));
221     }
222 
223     let discriminant_size = DiscriminantSize::from_count(body.variants.len()).ok_or_else(|| {
224         Error::new(
225             input.ident.span(),
226             "`enum`s with more than 2^32 variants are not supported",
227         )
228     })?;
229 
230     let cases = body
231         .variants
232         .iter()
233         .map(
234             |syn::Variant {
235                  attrs,
236                  ident,
237                  fields,
238                  ..
239              }| {
240                 Ok(VariantCase {
241                     attrs,
242                     ident,
243                     ty: match fields {
244                         syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
245                             Some(&fields.unnamed[0].ty)
246                         }
247                         syn::Fields::Unit => None,
248                         _ => {
249                             return Err(Error::new(
250                                 name.span(),
251                                 format!(
252                                     "`{}` component types can only be derived for Rust `enum`s \
253                                      containing variants with {}",
254                                     style,
255                                     match style {
256                                         VariantStyle::Variant => "at most one unnamed field each",
257                                         VariantStyle::Enum => "no fields",
258                                     }
259                                 ),
260                             ))
261                         }
262                     },
263                 })
264             },
265         )
266         .collect::<Result<Vec<_>>>()?;
267 
268     expander.expand_variant(
269         &input.ident,
270         &input.generics,
271         discriminant_size,
272         &cases,
273         style,
274         wasmtime_crate,
275     )
276 }
277 
278 fn expand_record_for_component_type(
279     name: &syn::Ident,
280     generics: &syn::Generics,
281     fields: &[&syn::Field],
282     typecheck: TokenStream,
283     typecheck_argument: TokenStream,
284     wt: &syn::Path,
285 ) -> Result<TokenStream> {
286     let internal = quote!(#wt::component::__internal);
287 
288     let mut lower_generic_params = TokenStream::new();
289     let mut lower_generic_args = TokenStream::new();
290     let mut lower_field_declarations = TokenStream::new();
291     let mut abi_list = TokenStream::new();
292     let mut unique_types = HashSet::new();
293 
294     for (index, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
295         let generic = format_ident!("T{}", index);
296 
297         lower_generic_params.extend(quote!(#generic: Copy,));
298         lower_generic_args.extend(quote!(<#ty as #wt::component::ComponentType>::Lower,));
299 
300         lower_field_declarations.extend(quote!(#ident: #generic,));
301 
302         abi_list.extend(quote!(
303             <#ty as #wt::component::ComponentType>::ABI,
304         ));
305 
306         unique_types.insert(ty);
307     }
308 
309     let generics = add_trait_bounds(generics, parse_quote!(#wt::component::ComponentType));
310     let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
311     let lower = format_ident!("Lower{}", name);
312 
313     // You may wonder why we make the types of all the fields of the #lower struct generic.  This is to work
314     // around the lack of [perfect derive support in
315     // rustc](https://smallcultfollowing.com/babysteps//blog/2022/04/12/implied-bounds-and-perfect-derive/#what-is-perfect-derive)
316     // as of this writing.
317     //
318     // If the struct we're deriving a `ComponentType` impl for has any generic parameters, then #lower needs
319     // generic parameters too.  And if we just copy the parameters and bounds from the impl to #lower, then the
320     // `#[derive(Clone, Copy)]` will fail unless the original generics were declared with those bounds, which
321     // we don't want to require.
322     //
323     // Alternatively, we could just pass the `Lower` associated type of each generic type as arguments to
324     // #lower, but that would require distinguishing between generic and concrete types when generating
325     // #lower_field_declarations, which would require some form of symbol resolution.  That doesn't seem worth
326     // the trouble.
327 
328     let expanded = quote! {
329         #[doc(hidden)]
330         #[derive(Clone, Copy)]
331         #[repr(C)]
332         pub struct #lower <#lower_generic_params> {
333             #lower_field_declarations
334             _align: [#wt::ValRaw; 0],
335         }
336 
337         unsafe impl #impl_generics #wt::component::ComponentType for #name #ty_generics #where_clause {
338             type Lower = #lower <#lower_generic_args>;
339 
340             const ABI: #internal::CanonicalAbiInfo =
341                 #internal::CanonicalAbiInfo::record_static(&[#abi_list]);
342 
343             #[inline]
344             fn typecheck(
345                 ty: &#internal::InterfaceType,
346                 types: &#internal::InstanceType<'_>,
347             ) -> #internal::anyhow::Result<()> {
348                 #internal::#typecheck(ty, types, &[#typecheck_argument])
349             }
350         }
351     };
352 
353     Ok(quote!(const _: () = { #expanded };))
354 }
355 
356 fn quote(size: DiscriminantSize, discriminant: usize) -> TokenStream {
357     match size {
358         DiscriminantSize::Size1 => {
359             let discriminant = u8::try_from(discriminant).unwrap();
360             quote!(#discriminant)
361         }
362         DiscriminantSize::Size2 => {
363             let discriminant = u16::try_from(discriminant).unwrap();
364             quote!(#discriminant)
365         }
366         DiscriminantSize::Size4 => {
367             let discriminant = u32::try_from(discriminant).unwrap();
368             quote!(#discriminant)
369         }
370     }
371 }
372 
373 pub struct LiftExpander;
374 
375 impl Expander for LiftExpander {
376     fn expand_record(
377         &self,
378         name: &syn::Ident,
379         generics: &syn::Generics,
380         fields: &[&syn::Field],
381         wt: &syn::Path,
382     ) -> Result<TokenStream> {
383         let internal = quote!(#wt::component::__internal);
384 
385         let mut lifts = TokenStream::new();
386         let mut loads = TokenStream::new();
387 
388         for (i, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
389             let field_ty = quote!(ty.fields[#i].ty);
390             lifts.extend(quote!(#ident: <#ty as #wt::component::Lift>::lift(
391                 cx, #field_ty, &src.#ident
392             )?,));
393 
394             loads.extend(quote!(#ident: <#ty as #wt::component::Lift>::load(
395                 cx, #field_ty,
396                 &bytes
397                     [<#ty as #wt::component::ComponentType>::ABI.next_field32_size(&mut offset)..]
398                     [..<#ty as #wt::component::ComponentType>::SIZE32]
399             )?,));
400         }
401 
402         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lift));
403         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
404 
405         let extract_ty = quote! {
406             let ty = match ty {
407                 #internal::InterfaceType::Record(i) => &cx.types[i],
408                 _ => #internal::bad_type_info(),
409             };
410         };
411 
412         let expanded = quote! {
413             unsafe impl #impl_generics #wt::component::Lift for #name #ty_generics #where_clause {
414                 #[inline]
415                 fn lift(
416                     cx: &mut #internal::LiftContext<'_>,
417                     ty: #internal::InterfaceType,
418                     src: &Self::Lower,
419                 ) -> #internal::anyhow::Result<Self> {
420                     #extract_ty
421                     Ok(Self {
422                         #lifts
423                     })
424                 }
425 
426                 #[inline]
427                 fn load(
428                     cx: &mut #internal::LiftContext<'_>,
429                     ty: #internal::InterfaceType,
430                     bytes: &[u8],
431                 ) -> #internal::anyhow::Result<Self> {
432                     #extract_ty
433                     debug_assert!(
434                         (bytes.as_ptr() as usize)
435                             % (<Self as #wt::component::ComponentType>::ALIGN32 as usize)
436                             == 0
437                     );
438                     let mut offset = 0;
439                     Ok(Self {
440                         #loads
441                     })
442                 }
443             }
444         };
445 
446         Ok(expanded)
447     }
448 
449     fn expand_variant(
450         &self,
451         name: &syn::Ident,
452         generics: &syn::Generics,
453         discriminant_size: DiscriminantSize,
454         cases: &[VariantCase],
455         style: VariantStyle,
456         wt: &syn::Path,
457     ) -> Result<TokenStream> {
458         let internal = quote!(#wt::component::__internal);
459 
460         let mut lifts = TokenStream::new();
461         let mut loads = TokenStream::new();
462 
463         let interface_type_variant = match style {
464             VariantStyle::Variant => quote!(Variant),
465             VariantStyle::Enum => quote!(Enum),
466         };
467 
468         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
469             let index_u32 = u32::try_from(index).unwrap();
470 
471             let index_quoted = quote(discriminant_size, index);
472 
473             if let Some(ty) = ty {
474                 let payload_ty = match style {
475                     VariantStyle::Variant => {
476                         quote!(ty.cases[#index].unwrap_or_else(#internal::bad_type_info))
477                     }
478                     VariantStyle::Enum => unreachable!(),
479                 };
480                 lifts.extend(
481                     quote!(#index_u32 => Self::#ident(<#ty as #wt::component::Lift>::lift(
482                         cx, #payload_ty, unsafe { &src.payload.#ident }
483                     )?),),
484                 );
485 
486                 loads.extend(
487                     quote!(#index_quoted => Self::#ident(<#ty as #wt::component::Lift>::load(
488                         cx, #payload_ty, &payload[..<#ty as #wt::component::ComponentType>::SIZE32]
489                     )?),),
490                 );
491             } else {
492                 lifts.extend(quote!(#index_u32 => Self::#ident,));
493 
494                 loads.extend(quote!(#index_quoted => Self::#ident,));
495             }
496         }
497 
498         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lift));
499         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
500 
501         let from_bytes = match discriminant_size {
502             DiscriminantSize::Size1 => quote!(bytes[0]),
503             DiscriminantSize::Size2 => quote!(u16::from_le_bytes(bytes[0..2].try_into()?)),
504             DiscriminantSize::Size4 => quote!(u32::from_le_bytes(bytes[0..4].try_into()?)),
505         };
506 
507         let extract_ty = quote! {
508             let ty = match ty {
509                 #internal::InterfaceType::#interface_type_variant(i) => &cx.types[i],
510                 _ => #internal::bad_type_info(),
511             };
512         };
513 
514         let expanded = quote! {
515             unsafe impl #impl_generics #wt::component::Lift for #name #ty_generics #where_clause {
516                 #[inline]
517                 fn lift(
518                     cx: &mut #internal::LiftContext<'_>,
519                     ty: #internal::InterfaceType,
520                     src: &Self::Lower,
521                 ) -> #internal::anyhow::Result<Self> {
522                     #extract_ty
523                     Ok(match src.tag.get_u32() {
524                         #lifts
525                         discrim => #internal::anyhow::bail!("unexpected discriminant: {}", discrim),
526                     })
527                 }
528 
529                 #[inline]
530                 fn load(
531                     cx: &mut #internal::LiftContext<'_>,
532                     ty: #internal::InterfaceType,
533                     bytes: &[u8],
534                 ) -> #internal::anyhow::Result<Self> {
535                     let align = <Self as #wt::component::ComponentType>::ALIGN32;
536                     debug_assert!((bytes.as_ptr() as usize) % (align as usize) == 0);
537                     let discrim = #from_bytes;
538                     let payload_offset = <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32;
539                     let payload = &bytes[payload_offset..];
540                     #extract_ty
541                     Ok(match discrim {
542                         #loads
543                         discrim => #internal::anyhow::bail!("unexpected discriminant: {}", discrim),
544                     })
545                 }
546             }
547         };
548 
549         Ok(expanded)
550     }
551 }
552 
553 pub struct LowerExpander;
554 
555 impl Expander for LowerExpander {
556     fn expand_record(
557         &self,
558         name: &syn::Ident,
559         generics: &syn::Generics,
560         fields: &[&syn::Field],
561         wt: &syn::Path,
562     ) -> Result<TokenStream> {
563         let internal = quote!(#wt::component::__internal);
564 
565         let mut lowers = TokenStream::new();
566         let mut stores = TokenStream::new();
567 
568         for (i, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
569             let field_ty = quote!(ty.fields[#i].ty);
570             lowers.extend(quote!(#wt::component::Lower::lower(
571                 &self.#ident, cx, #field_ty, #internal::map_maybe_uninit!(dst.#ident)
572             )?;));
573 
574             stores.extend(quote!(#wt::component::Lower::store(
575                 &self.#ident,
576                 cx,
577                 #field_ty,
578                 <#ty as #wt::component::ComponentType>::ABI.next_field32_size(&mut offset),
579             )?;));
580         }
581 
582         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lower));
583         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
584 
585         let extract_ty = quote! {
586             let ty = match ty {
587                 #internal::InterfaceType::Record(i) => &cx.types[i],
588                 _ => #internal::bad_type_info(),
589             };
590         };
591 
592         let expanded = quote! {
593             unsafe impl #impl_generics #wt::component::Lower for #name #ty_generics #where_clause {
594                 #[inline]
595                 fn lower<T>(
596                     &self,
597                     cx: &mut #internal::LowerContext<'_, T>,
598                     ty: #internal::InterfaceType,
599                     dst: &mut core::mem::MaybeUninit<Self::Lower>,
600                 ) -> #internal::anyhow::Result<()> {
601                     #extract_ty
602                     #lowers
603                     Ok(())
604                 }
605 
606                 #[inline]
607                 fn store<T>(
608                     &self,
609                     cx: &mut #internal::LowerContext<'_, T>,
610                     ty: #internal::InterfaceType,
611                     mut offset: usize
612                 ) -> #internal::anyhow::Result<()> {
613                     debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
614                     #extract_ty
615                     #stores
616                     Ok(())
617                 }
618             }
619         };
620 
621         Ok(expanded)
622     }
623 
624     fn expand_variant(
625         &self,
626         name: &syn::Ident,
627         generics: &syn::Generics,
628         discriminant_size: DiscriminantSize,
629         cases: &[VariantCase],
630         style: VariantStyle,
631         wt: &syn::Path,
632     ) -> Result<TokenStream> {
633         let internal = quote!(#wt::component::__internal);
634 
635         let mut lowers = TokenStream::new();
636         let mut stores = TokenStream::new();
637 
638         let interface_type_variant = match style {
639             VariantStyle::Variant => quote!(Variant),
640             VariantStyle::Enum => quote!(Enum),
641         };
642 
643         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
644             let index_u32 = u32::try_from(index).unwrap();
645 
646             let index_quoted = quote(discriminant_size, index);
647 
648             let discriminant_size = usize::from(discriminant_size);
649 
650             let pattern;
651             let lower;
652             let store;
653 
654             if ty.is_some() {
655                 let ty = match style {
656                     VariantStyle::Variant => {
657                         quote!(ty.cases[#index].unwrap_or_else(#internal::bad_type_info))
658                     }
659                     VariantStyle::Enum => unreachable!(),
660                 };
661                 pattern = quote!(Self::#ident(value));
662                 lower = quote!(value.lower(cx, #ty, dst));
663                 store = quote!(value.store(
664                     cx,
665                     #ty,
666                     offset + <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32,
667                 ));
668             } else {
669                 pattern = quote!(Self::#ident);
670                 lower = quote!(Ok(()));
671                 store = quote!(Ok(()));
672             }
673 
674             lowers.extend(quote!(#pattern => {
675                 #internal::map_maybe_uninit!(dst.tag).write(#wt::ValRaw::u32(#index_u32));
676                 unsafe {
677                     #internal::lower_payload(
678                         #internal::map_maybe_uninit!(dst.payload),
679                         |payload| #internal::map_maybe_uninit!(payload.#ident),
680                         |dst| #lower,
681                     )
682                 }
683             }));
684 
685             stores.extend(quote!(#pattern => {
686                 *cx.get::<#discriminant_size>(offset) = #index_quoted.to_le_bytes();
687                 #store
688             }));
689         }
690 
691         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lower));
692         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
693 
694         let extract_ty = quote! {
695             let ty = match ty {
696                 #internal::InterfaceType::#interface_type_variant(i) => &cx.types[i],
697                 _ => #internal::bad_type_info(),
698             };
699         };
700 
701         let expanded = quote! {
702             unsafe impl #impl_generics #wt::component::Lower for #name #ty_generics #where_clause {
703                 #[inline]
704                 fn lower<T>(
705                     &self,
706                     cx: &mut #internal::LowerContext<'_, T>,
707                     ty: #internal::InterfaceType,
708                     dst: &mut core::mem::MaybeUninit<Self::Lower>,
709                 ) -> #internal::anyhow::Result<()> {
710                     #extract_ty
711                     match self {
712                         #lowers
713                     }
714                 }
715 
716                 #[inline]
717                 fn store<T>(
718                     &self,
719                     cx: &mut #internal::LowerContext<'_, T>,
720                     ty: #internal::InterfaceType,
721                     mut offset: usize
722                 ) -> #internal::anyhow::Result<()> {
723                     #extract_ty
724                     debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
725                     match self {
726                         #stores
727                     }
728                 }
729             }
730         };
731 
732         Ok(expanded)
733     }
734 }
735 
736 pub struct ComponentTypeExpander;
737 
738 impl Expander for ComponentTypeExpander {
739     fn expand_record(
740         &self,
741         name: &syn::Ident,
742         generics: &syn::Generics,
743         fields: &[&syn::Field],
744         wt: &syn::Path,
745     ) -> Result<TokenStream> {
746         expand_record_for_component_type(
747             name,
748             generics,
749             fields,
750             quote!(typecheck_record),
751             fields
752                 .iter()
753                 .map(
754                     |syn::Field {
755                          attrs, ident, ty, ..
756                      }| {
757                         let name = find_rename(attrs)?.unwrap_or_else(|| {
758                             let ident = ident.as_ref().unwrap();
759                             syn::LitStr::new(&ident.to_string(), ident.span())
760                         });
761 
762                         Ok(quote!((#name, <#ty as #wt::component::ComponentType>::typecheck),))
763                     },
764                 )
765                 .collect::<Result<_>>()?,
766             wt,
767         )
768     }
769 
770     fn expand_variant(
771         &self,
772         name: &syn::Ident,
773         generics: &syn::Generics,
774         _discriminant_size: DiscriminantSize,
775         cases: &[VariantCase],
776         style: VariantStyle,
777         wt: &syn::Path,
778     ) -> Result<TokenStream> {
779         let internal = quote!(#wt::component::__internal);
780 
781         let mut case_names_and_checks = TokenStream::new();
782         let mut lower_payload_generic_params = TokenStream::new();
783         let mut lower_payload_generic_args = TokenStream::new();
784         let mut lower_payload_case_declarations = TokenStream::new();
785         let mut lower_generic_args = TokenStream::new();
786         let mut abi_list = TokenStream::new();
787         let mut unique_types = HashSet::new();
788 
789         for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() {
790             let rename = find_rename(attrs)?;
791 
792             let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span()));
793 
794             if let Some(ty) = ty {
795                 abi_list.extend(quote!(Some(<#ty as #wt::component::ComponentType>::ABI),));
796 
797                 case_names_and_checks.extend(match style {
798                     VariantStyle::Variant => {
799                         quote!((#name, Some(<#ty as #wt::component::ComponentType>::typecheck)),)
800                     }
801                     VariantStyle::Enum => {
802                         return Err(Error::new(
803                             ident.span(),
804                             "payloads are not permitted for `enum` cases",
805                         ))
806                     }
807                 });
808 
809                 let generic = format_ident!("T{}", index);
810 
811                 lower_payload_generic_params.extend(quote!(#generic: Copy,));
812                 lower_payload_generic_args.extend(quote!(#generic,));
813                 lower_payload_case_declarations.extend(quote!(#ident: #generic,));
814                 lower_generic_args.extend(quote!(<#ty as #wt::component::ComponentType>::Lower,));
815 
816                 unique_types.insert(ty);
817             } else {
818                 abi_list.extend(quote!(None,));
819                 case_names_and_checks.extend(match style {
820                     VariantStyle::Variant => {
821                         quote!((#name, None),)
822                     }
823                     VariantStyle::Enum => quote!(#name,),
824                 });
825                 lower_payload_case_declarations.extend(quote!(#ident: [#wt::ValRaw; 0],));
826             }
827         }
828 
829         let typecheck = match style {
830             VariantStyle::Variant => quote!(typecheck_variant),
831             VariantStyle::Enum => quote!(typecheck_enum),
832         };
833 
834         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::ComponentType));
835         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
836         let lower = format_ident!("Lower{}", name);
837         let lower_payload = format_ident!("LowerPayload{}", name);
838 
839         // You may wonder why we make the types of all the fields of the #lower struct and #lower_payload union
840         // generic.  This is to work around a [normalization bug in
841         // rustc](https://github.com/rust-lang/rust/issues/90903) such that the compiler does not understand that
842         // e.g. `<i32 as ComponentType>::Lower` is `Copy` despite the bound specified in `ComponentType`'s
843         // definition.
844         //
845         // See also the comment in `Self::expand_record` above for another reason why we do this.
846 
847         let expanded = quote! {
848             #[doc(hidden)]
849             #[derive(Clone, Copy)]
850             #[repr(C)]
851             pub struct #lower<#lower_payload_generic_params> {
852                 tag: #wt::ValRaw,
853                 payload: #lower_payload<#lower_payload_generic_args>
854             }
855 
856             #[doc(hidden)]
857             #[allow(non_snake_case)]
858             #[derive(Clone, Copy)]
859             #[repr(C)]
860             union #lower_payload<#lower_payload_generic_params> {
861                 #lower_payload_case_declarations
862             }
863 
864             unsafe impl #impl_generics #wt::component::ComponentType for #name #ty_generics #where_clause {
865                 type Lower = #lower<#lower_generic_args>;
866 
867                 #[inline]
868                 fn typecheck(
869                     ty: &#internal::InterfaceType,
870                     types: &#internal::InstanceType<'_>,
871                 ) -> #internal::anyhow::Result<()> {
872                     #internal::#typecheck(ty, types, &[#case_names_and_checks])
873                 }
874 
875                 const ABI: #internal::CanonicalAbiInfo =
876                     #internal::CanonicalAbiInfo::variant_static(&[#abi_list]);
877             }
878 
879             unsafe impl #impl_generics #internal::ComponentVariant for #name #ty_generics #where_clause {
880                 const CASES: &'static [Option<#internal::CanonicalAbiInfo>] = &[#abi_list];
881             }
882         };
883 
884         Ok(quote!(const _: () = { #expanded };))
885     }
886 }
887 
888 #[derive(Debug)]
889 struct Flag {
890     rename: Option<String>,
891     name: String,
892 }
893 
894 impl Parse for Flag {
895     fn parse(input: ParseStream) -> Result<Self> {
896         let attributes = syn::Attribute::parse_outer(input)?;
897 
898         let rename = find_rename(&attributes)?.map(|literal| literal.value());
899 
900         input.parse::<Token![const]>()?;
901         let name = input.parse::<syn::Ident>()?.to_string();
902 
903         Ok(Self { rename, name })
904     }
905 }
906 
907 #[derive(Debug)]
908 pub struct Flags {
909     name: String,
910     flags: Vec<Flag>,
911 }
912 
913 impl Parse for Flags {
914     fn parse(input: ParseStream) -> Result<Self> {
915         let name = input.parse::<syn::Ident>()?.to_string();
916 
917         let content;
918         braced!(content in input);
919 
920         let flags = content
921             .parse_terminated(Flag::parse, Token![;])?
922             .into_iter()
923             .collect();
924 
925         Ok(Self { name, flags })
926     }
927 }
928 
929 pub fn expand_flags(flags: &Flags) -> Result<TokenStream> {
930     let wt = default_wasmtime_crate();
931     let size = FlagsSize::from_count(flags.flags.len());
932 
933     let ty;
934     let eq;
935 
936     let count = flags.flags.len();
937 
938     match size {
939         FlagsSize::Size0 => {
940             ty = quote!(());
941             eq = quote!(true);
942         }
943         FlagsSize::Size1 => {
944             ty = quote!(u8);
945 
946             eq = if count == 8 {
947                 quote!(self.__inner0.eq(&rhs.__inner0))
948             } else {
949                 let mask = !(0xFF_u8 << count);
950 
951                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
952             };
953         }
954         FlagsSize::Size2 => {
955             ty = quote!(u16);
956 
957             eq = if count == 16 {
958                 quote!(self.__inner0.eq(&rhs.__inner0))
959             } else {
960                 let mask = !(0xFFFF_u16 << count);
961 
962                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
963             };
964         }
965         FlagsSize::Size4Plus(n) => {
966             ty = quote!(u32);
967 
968             let comparisons = (0..(n - 1))
969                 .map(|index| {
970                     let field = format_ident!("__inner{}", index);
971 
972                     quote!(self.#field.eq(&rhs.#field) &&)
973                 })
974                 .collect::<TokenStream>();
975 
976             let field = format_ident!("__inner{}", n - 1);
977 
978             eq = if count % 32 == 0 {
979                 quote!(#comparisons self.#field.eq(&rhs.#field))
980             } else {
981                 let mask = !(0xFFFF_FFFF_u32 << (count % 32));
982 
983                 quote!(#comparisons (self.#field & #mask).eq(&(rhs.#field & #mask)))
984             }
985         }
986     }
987 
988     let count;
989     let mut as_array;
990     let mut bitor;
991     let mut bitor_assign;
992     let mut bitand;
993     let mut bitand_assign;
994     let mut bitxor;
995     let mut bitxor_assign;
996     let mut not;
997 
998     match size {
999         FlagsSize::Size0 => {
1000             count = 0;
1001             as_array = quote!([]);
1002             bitor = quote!(Self {});
1003             bitor_assign = quote!();
1004             bitand = quote!(Self {});
1005             bitand_assign = quote!();
1006             bitxor = quote!(Self {});
1007             bitxor_assign = quote!();
1008             not = quote!(Self {});
1009         }
1010         FlagsSize::Size1 | FlagsSize::Size2 => {
1011             count = 1;
1012             as_array = quote!([self.__inner0 as u32]);
1013             bitor = quote!(Self {
1014                 __inner0: self.__inner0.bitor(rhs.__inner0)
1015             });
1016             bitor_assign = quote!(self.__inner0.bitor_assign(rhs.__inner0));
1017             bitand = quote!(Self {
1018                 __inner0: self.__inner0.bitand(rhs.__inner0)
1019             });
1020             bitand_assign = quote!(self.__inner0.bitand_assign(rhs.__inner0));
1021             bitxor = quote!(Self {
1022                 __inner0: self.__inner0.bitxor(rhs.__inner0)
1023             });
1024             bitxor_assign = quote!(self.__inner0.bitxor_assign(rhs.__inner0));
1025             not = quote!(Self {
1026                 __inner0: self.__inner0.not()
1027             });
1028         }
1029         FlagsSize::Size4Plus(n) => {
1030             count = usize::from(n);
1031             as_array = TokenStream::new();
1032             bitor = TokenStream::new();
1033             bitor_assign = TokenStream::new();
1034             bitand = TokenStream::new();
1035             bitand_assign = TokenStream::new();
1036             bitxor = TokenStream::new();
1037             bitxor_assign = TokenStream::new();
1038             not = TokenStream::new();
1039 
1040             for index in 0..n {
1041                 let field = format_ident!("__inner{}", index);
1042 
1043                 as_array.extend(quote!(self.#field,));
1044                 bitor.extend(quote!(#field: self.#field.bitor(rhs.#field),));
1045                 bitor_assign.extend(quote!(self.#field.bitor_assign(rhs.#field);));
1046                 bitand.extend(quote!(#field: self.#field.bitand(rhs.#field),));
1047                 bitand_assign.extend(quote!(self.#field.bitand_assign(rhs.#field);));
1048                 bitxor.extend(quote!(#field: self.#field.bitxor(rhs.#field),));
1049                 bitxor_assign.extend(quote!(self.#field.bitxor_assign(rhs.#field);));
1050                 not.extend(quote!(#field: self.#field.not(),));
1051             }
1052 
1053             as_array = quote!([#as_array]);
1054             bitor = quote!(Self { #bitor });
1055             bitand = quote!(Self { #bitand });
1056             bitxor = quote!(Self { #bitxor });
1057             not = quote!(Self { #not });
1058         }
1059     };
1060 
1061     let name = format_ident!("{}", flags.name);
1062 
1063     let mut constants = TokenStream::new();
1064     let mut rust_names = TokenStream::new();
1065     let mut component_names = TokenStream::new();
1066 
1067     for (index, Flag { name, rename }) in flags.flags.iter().enumerate() {
1068         rust_names.extend(quote!(#name,));
1069 
1070         let component_name = rename.as_ref().unwrap_or(name);
1071         component_names.extend(quote!(#component_name,));
1072 
1073         let fields = match size {
1074             FlagsSize::Size0 => quote!(),
1075             FlagsSize::Size1 => {
1076                 let init = 1_u8 << index;
1077                 quote!(__inner0: #init)
1078             }
1079             FlagsSize::Size2 => {
1080                 let init = 1_u16 << index;
1081                 quote!(__inner0: #init)
1082             }
1083             FlagsSize::Size4Plus(n) => (0..n)
1084                 .map(|i| {
1085                     let field = format_ident!("__inner{}", i);
1086 
1087                     let init = if index / 32 == usize::from(i) {
1088                         1_u32 << (index % 32)
1089                     } else {
1090                         0
1091                     };
1092 
1093                     quote!(#field: #init,)
1094                 })
1095                 .collect::<TokenStream>(),
1096         };
1097 
1098         let name = format_ident!("{}", name);
1099 
1100         constants.extend(quote!(pub const #name: Self = Self { #fields };));
1101     }
1102 
1103     let generics = syn::Generics {
1104         lt_token: None,
1105         params: Punctuated::new(),
1106         gt_token: None,
1107         where_clause: None,
1108     };
1109 
1110     let fields = {
1111         let ty = syn::parse2::<syn::Type>(ty.clone())?;
1112 
1113         (0..count)
1114             .map(|index| syn::Field {
1115                 attrs: Vec::new(),
1116                 vis: syn::Visibility::Inherited,
1117                 ident: Some(format_ident!("__inner{}", index)),
1118                 colon_token: None,
1119                 ty: ty.clone(),
1120                 mutability: syn::FieldMutability::None,
1121             })
1122             .collect::<Vec<_>>()
1123     };
1124 
1125     let fields = fields.iter().collect::<Vec<_>>();
1126 
1127     let component_type_impl = expand_record_for_component_type(
1128         &name,
1129         &generics,
1130         &fields,
1131         quote!(typecheck_flags),
1132         component_names,
1133         &wt,
1134     )?;
1135 
1136     let internal = quote!(#wt::component::__internal);
1137 
1138     let field_names = fields
1139         .iter()
1140         .map(|syn::Field { ident, .. }| ident)
1141         .collect::<Vec<_>>();
1142 
1143     let fields = fields
1144         .iter()
1145         .map(|syn::Field { ident, .. }| quote!(#[doc(hidden)] #ident: #ty,))
1146         .collect::<TokenStream>();
1147 
1148     let (field_interface_type, field_size) = match size {
1149         FlagsSize::Size0 => (quote!(NOT USED), 0usize),
1150         FlagsSize::Size1 => (quote!(#internal::InterfaceType::U8), 1),
1151         FlagsSize::Size2 => (quote!(#internal::InterfaceType::U16), 2),
1152         FlagsSize::Size4Plus(_) => (quote!(#internal::InterfaceType::U32), 4),
1153     };
1154 
1155     let expanded = quote! {
1156         #[derive(Copy, Clone, Default)]
1157         pub struct #name { #fields }
1158 
1159         impl #name {
1160             #constants
1161 
1162             pub fn as_array(&self) -> [u32; #count] {
1163                 #as_array
1164             }
1165 
1166             pub fn empty() -> Self {
1167                 Self::default()
1168             }
1169 
1170             pub fn all() -> Self {
1171                 use core::ops::Not;
1172                 Self::default().not()
1173             }
1174 
1175             pub fn contains(&self, other: Self) -> bool {
1176                 *self & other == other
1177             }
1178 
1179             pub fn intersects(&self, other: Self) -> bool {
1180                 *self & other != Self::empty()
1181             }
1182         }
1183 
1184         impl core::cmp::PartialEq for #name {
1185             fn eq(&self, rhs: &#name) -> bool {
1186                 #eq
1187             }
1188         }
1189 
1190         impl core::cmp::Eq for #name { }
1191 
1192         impl core::fmt::Debug for #name {
1193             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1194                 #internal::format_flags(&self.as_array(), &[#rust_names], f)
1195             }
1196         }
1197 
1198         impl core::ops::BitOr for #name {
1199             type Output = #name;
1200 
1201             fn bitor(self, rhs: #name) -> #name {
1202                 #bitor
1203             }
1204         }
1205 
1206         impl core::ops::BitOrAssign for #name {
1207             fn bitor_assign(&mut self, rhs: #name) {
1208                 #bitor_assign
1209             }
1210         }
1211 
1212         impl core::ops::BitAnd for #name {
1213             type Output = #name;
1214 
1215             fn bitand(self, rhs: #name) -> #name {
1216                 #bitand
1217             }
1218         }
1219 
1220         impl core::ops::BitAndAssign for #name {
1221             fn bitand_assign(&mut self, rhs: #name) {
1222                 #bitand_assign
1223             }
1224         }
1225 
1226         impl core::ops::BitXor for #name {
1227             type Output = #name;
1228 
1229             fn bitxor(self, rhs: #name) -> #name {
1230                 #bitxor
1231             }
1232         }
1233 
1234         impl core::ops::BitXorAssign for #name {
1235             fn bitxor_assign(&mut self, rhs: #name) {
1236                 #bitxor_assign
1237             }
1238         }
1239 
1240         impl core::ops::Not for #name {
1241             type Output = #name;
1242 
1243             fn not(self) -> #name {
1244                 #not
1245             }
1246         }
1247 
1248         #component_type_impl
1249 
1250         unsafe impl #wt::component::Lower for #name {
1251             fn lower<T>(
1252                 &self,
1253                 cx: &mut #internal::LowerContext<'_, T>,
1254                 _ty: #internal::InterfaceType,
1255                 dst: &mut core::mem::MaybeUninit<Self::Lower>,
1256             ) -> #internal::anyhow::Result<()> {
1257                 #(
1258                     self.#field_names.lower(
1259                         cx,
1260                         #field_interface_type,
1261                         #internal::map_maybe_uninit!(dst.#field_names),
1262                     )?;
1263                 )*
1264                 Ok(())
1265             }
1266 
1267             fn store<T>(
1268                 &self,
1269                 cx: &mut #internal::LowerContext<'_, T>,
1270                 _ty: #internal::InterfaceType,
1271                 mut offset: usize
1272             ) -> #internal::anyhow::Result<()> {
1273                 debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
1274                 #(
1275                     self.#field_names.store(
1276                         cx,
1277                         #field_interface_type,
1278                         offset,
1279                     )?;
1280                     offset += core::mem::size_of_val(&self.#field_names);
1281                 )*
1282                 Ok(())
1283             }
1284         }
1285 
1286         unsafe impl #wt::component::Lift for #name {
1287             fn lift(
1288                 cx: &mut #internal::LiftContext<'_>,
1289                 _ty: #internal::InterfaceType,
1290                 src: &Self::Lower,
1291             ) -> #internal::anyhow::Result<Self> {
1292                 Ok(Self {
1293                     #(
1294                         #field_names: #wt::component::Lift::lift(
1295                             cx,
1296                             #field_interface_type,
1297                             &src.#field_names,
1298                         )?,
1299                     )*
1300                 })
1301             }
1302 
1303             fn load(
1304                 cx: &mut #internal::LiftContext<'_>,
1305                 _ty: #internal::InterfaceType,
1306                 bytes: &[u8],
1307             ) -> #internal::anyhow::Result<Self> {
1308                 debug_assert!(
1309                     (bytes.as_ptr() as usize)
1310                         % (<Self as #wt::component::ComponentType>::ALIGN32 as usize)
1311                         == 0
1312                 );
1313                 #(
1314                     let (field, bytes) = bytes.split_at(#field_size);
1315                     let #field_names = #wt::component::Lift::load(
1316                         cx,
1317                         #field_interface_type,
1318                         field,
1319                     )?;
1320                 )*
1321                 Ok(Self { #(#field_names,)* })
1322             }
1323         }
1324     };
1325 
1326     Ok(expanded)
1327 }
1328