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