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_macro_input, parse_quote, Data, DeriveInput, Error, Result, Token};
8 use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9 
10 #[derive(Debug, Copy, Clone)]
11 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 struct VariantCase<'a> {
152     attrs: &'a [syn::Attribute],
153     ident: &'a syn::Ident,
154     ty: Option<&'a syn::Type>,
155 }
156 
157 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 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 #[proc_macro_derive(Lift, attributes(component))]
384 pub fn lift(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
385     expand(&LiftExpander, &parse_macro_input!(input as DeriveInput))
386         .unwrap_or_else(Error::into_compile_error)
387         .into()
388 }
389 
390 struct LiftExpander;
391 
392 impl Expander for LiftExpander {
393     fn expand_record(
394         &self,
395         name: &syn::Ident,
396         generics: &syn::Generics,
397         fields: &[&syn::Field],
398     ) -> Result<TokenStream> {
399         let internal = quote!(wasmtime::component::__internal);
400 
401         let mut lifts = TokenStream::new();
402         let mut loads = TokenStream::new();
403 
404         for syn::Field { ident, ty, .. } in fields {
405             lifts.extend(quote!(#ident: <#ty as wasmtime::component::Lift>::lift(
406                 store, options, &src.#ident
407             )?,));
408 
409             loads.extend(quote!(#ident: <#ty as wasmtime::component::Lift>::load(
410                 memory,
411                 &bytes
412                     [<#ty as wasmtime::component::ComponentType>::ABI.next_field32_size(&mut offset)..]
413                     [..<#ty as wasmtime::component::ComponentType>::SIZE32]
414             )?,));
415         }
416 
417         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::Lift));
418         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
419 
420         let expanded = quote! {
421             unsafe impl #impl_generics wasmtime::component::Lift for #name #ty_generics #where_clause {
422                 #[inline]
423                 fn lift(
424                     store: &#internal::StoreOpaque,
425                     options: &#internal::Options,
426                     src: &Self::Lower,
427                 ) -> #internal::anyhow::Result<Self> {
428                     Ok(Self {
429                         #lifts
430                     })
431                 }
432 
433                 #[inline]
434                 fn load(memory: &#internal::Memory, bytes: &[u8]) -> #internal::anyhow::Result<Self> {
435                     debug_assert!(
436                         (bytes.as_ptr() as usize)
437                             % (<Self as wasmtime::component::ComponentType>::ALIGN32 as usize)
438                             == 0
439                     );
440                     let mut offset = 0;
441                     Ok(Self {
442                         #loads
443                     })
444                 }
445             }
446         };
447 
448         Ok(expanded)
449     }
450 
451     fn expand_variant(
452         &self,
453         name: &syn::Ident,
454         generics: &syn::Generics,
455         discriminant_size: DiscriminantSize,
456         cases: &[VariantCase],
457         _style: VariantStyle,
458     ) -> Result<TokenStream> {
459         let internal = quote!(wasmtime::component::__internal);
460 
461         let mut lifts = TokenStream::new();
462         let mut loads = TokenStream::new();
463 
464         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
465             let index_u32 = u32::try_from(index).unwrap();
466 
467             let index_quoted = quote(discriminant_size, index);
468 
469             if let Some(ty) = ty {
470                 lifts.extend(
471                     quote!(#index_u32 => Self::#ident(<#ty as wasmtime::component::Lift>::lift(
472                         store, options, unsafe { &src.payload.#ident }
473                     )?),),
474                 );
475 
476                 loads.extend(
477                     quote!(#index_quoted => Self::#ident(<#ty as wasmtime::component::Lift>::load(
478                         memory, &payload[..<#ty as wasmtime::component::ComponentType>::SIZE32]
479                     )?),),
480                 );
481             } else {
482                 lifts.extend(quote!(#index_u32 => Self::#ident,));
483 
484                 loads.extend(quote!(#index_quoted => Self::#ident,));
485             }
486         }
487 
488         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::Lift));
489         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
490 
491         let from_bytes = match discriminant_size {
492             DiscriminantSize::Size1 => quote!(bytes[0]),
493             DiscriminantSize::Size2 => quote!(u16::from_le_bytes(bytes[0..2].try_into()?)),
494             DiscriminantSize::Size4 => quote!(u32::from_le_bytes(bytes[0..4].try_into()?)),
495         };
496 
497         let expanded = quote! {
498             unsafe impl #impl_generics wasmtime::component::Lift for #name #ty_generics #where_clause {
499                 #[inline]
500                 fn lift(
501                     store: &#internal::StoreOpaque,
502                     options: &#internal::Options,
503                     src: &Self::Lower,
504                 ) -> #internal::anyhow::Result<Self> {
505                     Ok(match src.tag.get_u32() {
506                         #lifts
507                         discrim => #internal::anyhow::bail!("unexpected discriminant: {}", discrim),
508                     })
509                 }
510 
511                 #[inline]
512                 fn load(memory: &#internal::Memory, bytes: &[u8]) -> #internal::anyhow::Result<Self> {
513                     let align = <Self as wasmtime::component::ComponentType>::ALIGN32;
514                     debug_assert!((bytes.as_ptr() as usize) % (align as usize) == 0);
515                     let discrim = #from_bytes;
516                     let payload_offset = <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32;
517                     let payload = &bytes[payload_offset..];
518                     Ok(match discrim {
519                         #loads
520                         discrim => #internal::anyhow::bail!("unexpected discriminant: {}", discrim),
521                     })
522                 }
523             }
524         };
525 
526         Ok(expanded)
527     }
528 }
529 
530 #[proc_macro_derive(Lower, attributes(component))]
531 pub fn lower(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
532     expand(&LowerExpander, &parse_macro_input!(input as DeriveInput))
533         .unwrap_or_else(Error::into_compile_error)
534         .into()
535 }
536 
537 struct LowerExpander;
538 
539 impl Expander for LowerExpander {
540     fn expand_record(
541         &self,
542         name: &syn::Ident,
543         generics: &syn::Generics,
544         fields: &[&syn::Field],
545     ) -> Result<TokenStream> {
546         let internal = quote!(wasmtime::component::__internal);
547 
548         let mut lowers = TokenStream::new();
549         let mut stores = TokenStream::new();
550 
551         for syn::Field { ident, ty, .. } in fields {
552             lowers.extend(quote!(wasmtime::component::Lower::lower(
553                 &self.#ident, store, options, #internal::map_maybe_uninit!(dst.#ident)
554             )?;));
555 
556             stores.extend(quote!(wasmtime::component::Lower::store(
557                 &self.#ident,
558                 memory,
559                 <#ty as wasmtime::component::ComponentType>::ABI.next_field32_size(&mut offset),
560             )?;));
561         }
562 
563         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::Lower));
564         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
565 
566         let expanded = quote! {
567             unsafe impl #impl_generics wasmtime::component::Lower for #name #ty_generics #where_clause {
568                 #[inline]
569                 fn lower<T>(
570                     &self,
571                     store: &mut wasmtime::StoreContextMut<T>,
572                     options: &#internal::Options,
573                     dst: &mut std::mem::MaybeUninit<Self::Lower>,
574                 ) -> #internal::anyhow::Result<()> {
575                     #lowers
576                     Ok(())
577                 }
578 
579                 #[inline]
580                 fn store<T>(
581                     &self,
582                     memory: &mut #internal::MemoryMut<'_, T>,
583                     mut offset: usize
584                 ) -> #internal::anyhow::Result<()> {
585                     debug_assert!(offset % (<Self as wasmtime::component::ComponentType>::ALIGN32 as usize) == 0);
586                     #stores
587                     Ok(())
588                 }
589             }
590         };
591 
592         Ok(expanded)
593     }
594 
595     fn expand_variant(
596         &self,
597         name: &syn::Ident,
598         generics: &syn::Generics,
599         discriminant_size: DiscriminantSize,
600         cases: &[VariantCase],
601         _style: VariantStyle,
602     ) -> Result<TokenStream> {
603         let internal = quote!(wasmtime::component::__internal);
604 
605         let mut lowers = TokenStream::new();
606         let mut stores = TokenStream::new();
607 
608         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
609             let index_u32 = u32::try_from(index).unwrap();
610 
611             let index_quoted = quote(discriminant_size, index);
612 
613             let discriminant_size = usize::from(discriminant_size);
614 
615             let pattern;
616             let lower;
617             let store;
618 
619             if ty.is_some() {
620                 pattern = quote!(Self::#ident(value));
621                 lower = quote!(value.lower(store, options, dst));
622                 store = quote!(value.store(
623                     memory,
624                     offset + <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32,
625                 ));
626             } else {
627                 pattern = quote!(Self::#ident);
628                 lower = quote!(Ok(()));
629                 store = quote!(Ok(()));
630             }
631 
632             lowers.extend(quote!(#pattern => {
633                 #internal::map_maybe_uninit!(dst.tag).write(wasmtime::ValRaw::u32(#index_u32));
634                 unsafe {
635                     #internal::lower_payload(
636                         #internal::map_maybe_uninit!(dst.payload),
637                         |payload| #internal::map_maybe_uninit!(payload.#ident),
638                         |dst| #lower,
639                     )
640                 }
641             }));
642 
643             stores.extend(quote!(#pattern => {
644                 *memory.get::<#discriminant_size>(offset) = #index_quoted.to_le_bytes();
645                 #store
646             }));
647         }
648 
649         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::Lower));
650         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
651 
652         let expanded = quote! {
653             unsafe impl #impl_generics wasmtime::component::Lower for #name #ty_generics #where_clause {
654                 #[inline]
655                 fn lower<T>(
656                     &self,
657                     store: &mut wasmtime::StoreContextMut<T>,
658                     options: &#internal::Options,
659                     dst: &mut std::mem::MaybeUninit<Self::Lower>,
660                 ) -> #internal::anyhow::Result<()> {
661                     match self {
662                         #lowers
663                     }
664                 }
665 
666                 #[inline]
667                 fn store<T>(
668                     &self,
669                     memory: &mut #internal::MemoryMut<'_, T>,
670                     mut offset: usize
671                 ) -> #internal::anyhow::Result<()> {
672                     debug_assert!(offset % (<Self as wasmtime::component::ComponentType>::ALIGN32 as usize) == 0);
673                     match self {
674                         #stores
675                     }
676                 }
677             }
678         };
679 
680         Ok(expanded)
681     }
682 }
683 
684 #[proc_macro_derive(ComponentType, attributes(component))]
685 pub fn component_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
686     expand(
687         &ComponentTypeExpander,
688         &parse_macro_input!(input as DeriveInput),
689     )
690     .unwrap_or_else(Error::into_compile_error)
691     .into()
692 }
693 
694 struct ComponentTypeExpander;
695 
696 impl Expander for ComponentTypeExpander {
697     fn expand_record(
698         &self,
699         name: &syn::Ident,
700         generics: &syn::Generics,
701         fields: &[&syn::Field],
702     ) -> Result<TokenStream> {
703         expand_record_for_component_type(
704             name,
705             generics,
706             fields,
707             quote!(typecheck_record),
708             fields
709                 .iter()
710                 .map(
711                     |syn::Field {
712                          attrs, ident, ty, ..
713                      }| {
714                         let name = find_rename(attrs)?.unwrap_or_else(|| {
715                             Literal::string(&ident.as_ref().unwrap().to_string())
716                         });
717 
718                         Ok(quote!((#name, <#ty as wasmtime::component::ComponentType>::typecheck),))
719                     },
720                 )
721                 .collect::<Result<_>>()?,
722         )
723     }
724 
725     fn expand_variant(
726         &self,
727         name: &syn::Ident,
728         generics: &syn::Generics,
729         _discriminant_size: DiscriminantSize,
730         cases: &[VariantCase],
731         style: VariantStyle,
732     ) -> Result<TokenStream> {
733         let internal = quote!(wasmtime::component::__internal);
734 
735         let mut case_names_and_checks = TokenStream::new();
736         let mut lower_payload_generic_params = TokenStream::new();
737         let mut lower_payload_generic_args = TokenStream::new();
738         let mut lower_payload_case_declarations = TokenStream::new();
739         let mut lower_generic_args = TokenStream::new();
740         let mut abi_list = TokenStream::new();
741         let mut unique_types = HashSet::new();
742 
743         for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() {
744             let rename = find_rename(attrs)?;
745 
746             if let (Some(_), VariantStyle::Union) = (&rename, style) {
747                 return Err(Error::new(
748                     ident.span(),
749                     "renaming `union` cases is not permitted; only the type is used",
750                 ));
751             }
752 
753             let name = rename.unwrap_or_else(|| Literal::string(&ident.to_string()));
754 
755             if let Some(ty) = ty {
756                 abi_list.extend(quote!(Some(<#ty as wasmtime::component::ComponentType>::ABI),));
757 
758                 case_names_and_checks.extend(match style {
759                     VariantStyle::Variant => {
760                         quote!((#name, Some(<#ty as wasmtime::component::ComponentType>::typecheck)),)
761                     }
762                     VariantStyle::Union => {
763                         quote!(<#ty as wasmtime::component::ComponentType>::typecheck,)
764                     }
765                     VariantStyle::Enum => {
766                         return Err(Error::new(
767                             ident.span(),
768                             "payloads are not permitted for `enum` cases",
769                         ))
770                     }
771                 });
772 
773                 let generic = format_ident!("T{}", index);
774 
775                 lower_payload_generic_params.extend(quote!(#generic: Copy,));
776                 lower_payload_generic_args.extend(quote!(#generic,));
777                 lower_payload_case_declarations.extend(quote!(#ident: #generic,));
778                 lower_generic_args
779                     .extend(quote!(<#ty as wasmtime::component::ComponentType>::Lower,));
780 
781                 unique_types.insert(ty);
782             } else {
783                 abi_list.extend(quote!(None,));
784                 case_names_and_checks.extend(match style {
785                     VariantStyle::Variant => {
786                         quote!((#name, None),)
787                     }
788                     VariantStyle::Union => {
789                         quote!(<() as wasmtime::component::ComponentType>::typecheck,)
790                     }
791                     VariantStyle::Enum => quote!(#name,),
792                 });
793                 lower_payload_case_declarations.extend(quote!(#ident: [wasmtime::ValRaw; 0],));
794             }
795         }
796 
797         let typecheck = match style {
798             VariantStyle::Variant => quote!(typecheck_variant),
799             VariantStyle::Union => quote!(typecheck_union),
800             VariantStyle::Enum => quote!(typecheck_enum),
801         };
802 
803         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::ComponentType));
804         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
805         let lower = format_ident!("Lower{}", name);
806         let lower_payload = format_ident!("LowerPayload{}", name);
807 
808         // You may wonder why we make the types of all the fields of the #lower struct and #lower_payload union
809         // generic.  This is to work around a [normalization bug in
810         // rustc](https://github.com/rust-lang/rust/issues/90903) such that the compiler does not understand that
811         // e.g. `<i32 as ComponentType>::Lower` is `Copy` despite the bound specified in `ComponentType`'s
812         // definition.
813         //
814         // See also the comment in `Self::expand_record` above for another reason why we do this.
815 
816         let expanded = quote! {
817             #[doc(hidden)]
818             #[derive(Clone, Copy)]
819             #[repr(C)]
820             pub struct #lower<#lower_payload_generic_params> {
821                 tag: wasmtime::ValRaw,
822                 payload: #lower_payload<#lower_payload_generic_args>
823             }
824 
825             #[doc(hidden)]
826             #[allow(non_snake_case)]
827             #[derive(Clone, Copy)]
828             #[repr(C)]
829             union #lower_payload<#lower_payload_generic_params> {
830                 #lower_payload_case_declarations
831             }
832 
833             unsafe impl #impl_generics wasmtime::component::ComponentType for #name #ty_generics #where_clause {
834                 type Lower = #lower<#lower_generic_args>;
835 
836                 #[inline]
837                 fn typecheck(
838                     ty: &#internal::InterfaceType,
839                     types: &#internal::ComponentTypes,
840                 ) -> #internal::anyhow::Result<()> {
841                     #internal::#typecheck(ty, types, &[#case_names_and_checks])
842                 }
843 
844                 const ABI: #internal::CanonicalAbiInfo =
845                     #internal::CanonicalAbiInfo::variant_static(&[#abi_list]);
846             }
847 
848             unsafe impl #impl_generics #internal::ComponentVariant for #name #ty_generics #where_clause {
849                 const CASES: &'static [Option<#internal::CanonicalAbiInfo>] = &[#abi_list];
850             }
851         };
852 
853         Ok(quote!(const _: () = { #expanded };))
854     }
855 }
856 
857 #[derive(Debug)]
858 struct Flag {
859     rename: Option<String>,
860     name: String,
861 }
862 
863 impl Parse for Flag {
864     fn parse(input: ParseStream) -> Result<Self> {
865         let attributes = syn::Attribute::parse_outer(input)?;
866 
867         let rename = find_rename(&attributes)?
868             .map(|literal| {
869                 let s = literal.to_string();
870 
871                 s.strip_prefix('"')
872                     .and_then(|s| s.strip_suffix('"'))
873                     .map(|s| s.to_owned())
874                     .ok_or_else(|| Error::new(literal.span(), "expected string literal"))
875             })
876             .transpose()?;
877 
878         input.parse::<Token![const]>()?;
879         let name = input.parse::<syn::Ident>()?.to_string();
880 
881         Ok(Self { rename, name })
882     }
883 }
884 
885 #[derive(Debug)]
886 struct Flags {
887     name: String,
888     flags: Vec<Flag>,
889 }
890 
891 impl Parse for Flags {
892     fn parse(input: ParseStream) -> Result<Self> {
893         let name = input.parse::<syn::Ident>()?.to_string();
894 
895         let content;
896         braced!(content in input);
897 
898         let flags = content
899             .parse_terminated::<_, Token![;]>(Flag::parse)?
900             .into_iter()
901             .collect();
902 
903         Ok(Self { name, flags })
904     }
905 }
906 
907 #[proc_macro]
908 pub fn flags(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
909     expand_flags(&parse_macro_input!(input as Flags))
910         .unwrap_or_else(Error::into_compile_error)
911         .into()
912 }
913 
914 fn expand_flags(flags: &Flags) -> Result<TokenStream> {
915     let size = FlagsSize::from_count(flags.flags.len());
916 
917     let ty;
918     let eq;
919 
920     let count = flags.flags.len();
921 
922     match size {
923         FlagsSize::Size0 => {
924             ty = quote!(());
925             eq = quote!(true);
926         }
927         FlagsSize::Size1 => {
928             ty = quote!(u8);
929 
930             eq = if count == 8 {
931                 quote!(self.__inner0.eq(&rhs.__inner0))
932             } else {
933                 let mask = !(0xFF_u8 << count);
934 
935                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
936             };
937         }
938         FlagsSize::Size2 => {
939             ty = quote!(u16);
940 
941             eq = if count == 16 {
942                 quote!(self.__inner0.eq(&rhs.__inner0))
943             } else {
944                 let mask = !(0xFFFF_u16 << count);
945 
946                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
947             };
948         }
949         FlagsSize::Size4Plus(n) => {
950             ty = quote!(u32);
951 
952             let comparisons = (0..(n - 1))
953                 .map(|index| {
954                     let field = format_ident!("__inner{}", index);
955 
956                     quote!(self.#field.eq(&rhs.#field) &&)
957                 })
958                 .collect::<TokenStream>();
959 
960             let field = format_ident!("__inner{}", n - 1);
961 
962             eq = if count % 32 == 0 {
963                 quote!(#comparisons self.#field.eq(&rhs.#field))
964             } else {
965                 let mask = !(0xFFFF_FFFF_u32 << (count % 32));
966 
967                 quote!(#comparisons (self.#field & #mask).eq(&(rhs.#field & #mask)))
968             }
969         }
970     }
971 
972     let count;
973     let mut as_array;
974     let mut bitor;
975     let mut bitor_assign;
976     let mut bitand;
977     let mut bitand_assign;
978     let mut bitxor;
979     let mut bitxor_assign;
980     let mut not;
981 
982     match size {
983         FlagsSize::Size0 => {
984             count = 0;
985             as_array = quote!([]);
986             bitor = quote!(Self {});
987             bitor_assign = quote!();
988             bitand = quote!(Self {});
989             bitand_assign = quote!();
990             bitxor = quote!(Self {});
991             bitxor_assign = quote!();
992             not = quote!(Self {});
993         }
994         FlagsSize::Size1 | FlagsSize::Size2 => {
995             count = 1;
996             as_array = quote!([self.__inner0 as u32]);
997             bitor = quote!(Self {
998                 __inner0: self.__inner0.bitor(rhs.__inner0)
999             });
1000             bitor_assign = quote!(self.__inner0.bitor_assign(rhs.__inner0));
1001             bitand = quote!(Self {
1002                 __inner0: self.__inner0.bitand(rhs.__inner0)
1003             });
1004             bitand_assign = quote!(self.__inner0.bitand_assign(rhs.__inner0));
1005             bitxor = quote!(Self {
1006                 __inner0: self.__inner0.bitxor(rhs.__inner0)
1007             });
1008             bitxor_assign = quote!(self.__inner0.bitxor_assign(rhs.__inner0));
1009             not = quote!(Self {
1010                 __inner0: self.__inner0.not()
1011             });
1012         }
1013         FlagsSize::Size4Plus(n) => {
1014             count = usize::from(n);
1015             as_array = TokenStream::new();
1016             bitor = TokenStream::new();
1017             bitor_assign = TokenStream::new();
1018             bitand = TokenStream::new();
1019             bitand_assign = TokenStream::new();
1020             bitxor = TokenStream::new();
1021             bitxor_assign = TokenStream::new();
1022             not = TokenStream::new();
1023 
1024             for index in 0..n {
1025                 let field = format_ident!("__inner{}", index);
1026 
1027                 as_array.extend(quote!(self.#field,));
1028                 bitor.extend(quote!(#field: self.#field.bitor(rhs.#field),));
1029                 bitor_assign.extend(quote!(self.#field.bitor_assign(rhs.#field);));
1030                 bitand.extend(quote!(#field: self.#field.bitand(rhs.#field),));
1031                 bitand_assign.extend(quote!(self.#field.bitand_assign(rhs.#field);));
1032                 bitxor.extend(quote!(#field: self.#field.bitxor(rhs.#field),));
1033                 bitxor_assign.extend(quote!(self.#field.bitxor_assign(rhs.#field);));
1034                 not.extend(quote!(#field: self.#field.not(),));
1035             }
1036 
1037             as_array = quote!([#as_array]);
1038             bitor = quote!(Self { #bitor });
1039             bitand = quote!(Self { #bitand });
1040             bitxor = quote!(Self { #bitxor });
1041             not = quote!(Self { #not });
1042         }
1043     };
1044 
1045     let name = format_ident!("{}", flags.name);
1046 
1047     let mut constants = TokenStream::new();
1048     let mut rust_names = TokenStream::new();
1049     let mut component_names = TokenStream::new();
1050 
1051     for (index, Flag { name, rename }) in flags.flags.iter().enumerate() {
1052         rust_names.extend(quote!(#name,));
1053 
1054         let component_name = rename.as_ref().unwrap_or(name);
1055         component_names.extend(quote!(#component_name,));
1056 
1057         let fields = match size {
1058             FlagsSize::Size0 => quote!(),
1059             FlagsSize::Size1 => {
1060                 let init = 1_u8 << index;
1061                 quote!(__inner0: #init)
1062             }
1063             FlagsSize::Size2 => {
1064                 let init = 1_u16 << index;
1065                 quote!(__inner0: #init)
1066             }
1067             FlagsSize::Size4Plus(n) => (0..n)
1068                 .map(|i| {
1069                     let field = format_ident!("__inner{}", i);
1070 
1071                     let init = if index / 32 == usize::from(i) {
1072                         1_u32 << (index % 32)
1073                     } else {
1074                         0
1075                     };
1076 
1077                     quote!(#field: #init,)
1078                 })
1079                 .collect::<TokenStream>(),
1080         };
1081 
1082         let name = format_ident!("{}", name);
1083 
1084         constants.extend(quote!(const #name: Self = Self { #fields };));
1085     }
1086 
1087     let generics = syn::Generics {
1088         lt_token: None,
1089         params: Punctuated::new(),
1090         gt_token: None,
1091         where_clause: None,
1092     };
1093 
1094     let fields = {
1095         let ty = syn::parse2::<syn::Type>(ty.clone())?;
1096 
1097         (0..count)
1098             .map(|index| syn::Field {
1099                 attrs: Vec::new(),
1100                 vis: syn::Visibility::Inherited,
1101                 ident: Some(format_ident!("__inner{}", index)),
1102                 colon_token: None,
1103                 ty: ty.clone(),
1104             })
1105             .collect::<Vec<_>>()
1106     };
1107 
1108     let fields = fields.iter().collect::<Vec<_>>();
1109 
1110     let component_type_impl = expand_record_for_component_type(
1111         &name,
1112         &generics,
1113         &fields,
1114         quote!(typecheck_flags),
1115         component_names,
1116     )?;
1117 
1118     let lower_impl = LowerExpander.expand_record(&name, &generics, &fields)?;
1119 
1120     let lift_impl = LiftExpander.expand_record(&name, &generics, &fields)?;
1121 
1122     let internal = quote!(wasmtime::component::__internal);
1123 
1124     let fields = fields
1125         .iter()
1126         .map(|syn::Field { ident, .. }| quote!(#[doc(hidden)] #ident: #ty,))
1127         .collect::<TokenStream>();
1128 
1129     let expanded = quote! {
1130         #[derive(Copy, Clone, Default)]
1131         struct #name { #fields }
1132 
1133         impl #name {
1134             #constants
1135 
1136             fn as_array(&self) -> [u32; #count] {
1137                 #as_array
1138             }
1139         }
1140 
1141         impl std::cmp::PartialEq for #name {
1142             fn eq(&self, rhs: &#name) -> bool {
1143                 #eq
1144             }
1145         }
1146 
1147         impl std::cmp::Eq for #name { }
1148 
1149         impl std::fmt::Debug for #name {
1150             fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1151                 #internal::format_flags(&self.as_array(), &[#rust_names], f)
1152             }
1153         }
1154 
1155         impl std::ops::BitOr for #name {
1156             type Output = #name;
1157 
1158             fn bitor(self, rhs: #name) -> #name {
1159                 #bitor
1160             }
1161         }
1162 
1163         impl std::ops::BitOrAssign for #name {
1164             fn bitor_assign(&mut self, rhs: #name) {
1165                 #bitor_assign
1166             }
1167         }
1168 
1169         impl std::ops::BitAnd for #name {
1170             type Output = #name;
1171 
1172             fn bitand(self, rhs: #name) -> #name {
1173                 #bitand
1174             }
1175         }
1176 
1177         impl std::ops::BitAndAssign for #name {
1178             fn bitand_assign(&mut self, rhs: #name) {
1179                 #bitand_assign
1180             }
1181         }
1182 
1183         impl std::ops::BitXor for #name {
1184             type Output = #name;
1185 
1186             fn bitxor(self, rhs: #name) -> #name {
1187                 #bitxor
1188             }
1189         }
1190 
1191         impl std::ops::BitXorAssign for #name {
1192             fn bitxor_assign(&mut self, rhs: #name) {
1193                 #bitxor_assign
1194             }
1195         }
1196 
1197         impl std::ops::Not for #name {
1198             type Output = #name;
1199 
1200             fn not(self) -> #name {
1201                 #not
1202             }
1203         }
1204 
1205         #component_type_impl
1206 
1207         #lower_impl
1208 
1209         #lift_impl
1210     };
1211 
1212     Ok(expanded)
1213 }
1214