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