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, #internal::map_maybe_uninit!(dst.payload.#ident)));
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::i32(#index_u32 as i32));
634                 #lower
635             }));
636 
637             stores.extend(quote!(#pattern => {
638                 *memory.get::<#discriminant_size>(offset) = #index_quoted.to_le_bytes();
639                 #store
640             }));
641         }
642 
643         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::Lower));
644         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
645 
646         let expanded = quote! {
647             unsafe impl #impl_generics wasmtime::component::Lower for #name #ty_generics #where_clause {
648                 #[inline]
649                 fn lower<T>(
650                     &self,
651                     store: &mut wasmtime::StoreContextMut<T>,
652                     options: &#internal::Options,
653                     dst: &mut std::mem::MaybeUninit<Self::Lower>,
654                 ) -> #internal::anyhow::Result<()> {
655                     // See comment in <Result<T, E> as Lower>::lower for why we zero out the payload here
656                     unsafe {
657                         #internal::map_maybe_uninit!(dst.payload)
658                             .as_mut_ptr()
659                             .write_bytes(0u8, 1);
660                     }
661 
662                     match self {
663                         #lowers
664                     }
665                 }
666 
667                 #[inline]
668                 fn store<T>(
669                     &self,
670                     memory: &mut #internal::MemoryMut<'_, T>,
671                     mut offset: usize
672                 ) -> #internal::anyhow::Result<()> {
673                     debug_assert!(offset % (<Self as wasmtime::component::ComponentType>::ALIGN32 as usize) == 0);
674                     match self {
675                         #stores
676                     }
677                 }
678             }
679         };
680 
681         Ok(expanded)
682     }
683 }
684 
685 #[proc_macro_derive(ComponentType, attributes(component))]
686 pub fn component_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
687     expand(
688         &ComponentTypeExpander,
689         &parse_macro_input!(input as DeriveInput),
690     )
691     .unwrap_or_else(Error::into_compile_error)
692     .into()
693 }
694 
695 struct ComponentTypeExpander;
696 
697 impl Expander for ComponentTypeExpander {
698     fn expand_record(
699         &self,
700         name: &syn::Ident,
701         generics: &syn::Generics,
702         fields: &[&syn::Field],
703     ) -> Result<TokenStream> {
704         expand_record_for_component_type(
705             name,
706             generics,
707             fields,
708             quote!(typecheck_record),
709             fields
710                 .iter()
711                 .map(
712                     |syn::Field {
713                          attrs, ident, ty, ..
714                      }| {
715                         let name = find_rename(attrs)?.unwrap_or_else(|| {
716                             Literal::string(&ident.as_ref().unwrap().to_string())
717                         });
718 
719                         Ok(quote!((#name, <#ty as wasmtime::component::ComponentType>::typecheck),))
720                     },
721                 )
722                 .collect::<Result<_>>()?,
723         )
724     }
725 
726     fn expand_variant(
727         &self,
728         name: &syn::Ident,
729         generics: &syn::Generics,
730         _discriminant_size: DiscriminantSize,
731         cases: &[VariantCase],
732         style: VariantStyle,
733     ) -> Result<TokenStream> {
734         let internal = quote!(wasmtime::component::__internal);
735 
736         let mut case_names_and_checks = TokenStream::new();
737         let mut lower_payload_generic_params = TokenStream::new();
738         let mut lower_payload_generic_args = TokenStream::new();
739         let mut lower_payload_case_declarations = TokenStream::new();
740         let mut lower_generic_args = TokenStream::new();
741         let mut abi_list = TokenStream::new();
742         let mut unique_types = HashSet::new();
743 
744         for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() {
745             let rename = find_rename(attrs)?;
746 
747             if let (Some(_), VariantStyle::Union) = (&rename, style) {
748                 return Err(Error::new(
749                     ident.span(),
750                     "renaming `union` cases is not permitted; only the type is used",
751                 ));
752             }
753 
754             let name = rename.unwrap_or_else(|| Literal::string(&ident.to_string()));
755 
756             if let Some(ty) = ty {
757                 abi_list.extend(quote!(<#ty as wasmtime::component::ComponentType>::ABI,));
758 
759                 case_names_and_checks.extend(match style {
760                     VariantStyle::Variant => {
761                         quote!((#name, <#ty as wasmtime::component::ComponentType>::typecheck),)
762                     }
763                     VariantStyle::Union => {
764                         quote!(<#ty as wasmtime::component::ComponentType>::typecheck,)
765                     }
766                     VariantStyle::Enum => {
767                         return Err(Error::new(
768                             ident.span(),
769                             "payloads are not permitted for `enum` cases",
770                         ))
771                     }
772                 });
773 
774                 let generic = format_ident!("T{}", index);
775 
776                 lower_payload_generic_params.extend(quote!(#generic: Copy,));
777                 lower_payload_generic_args.extend(quote!(#generic,));
778                 lower_payload_case_declarations.extend(quote!(#ident: #generic,));
779                 lower_generic_args
780                     .extend(quote!(<#ty as wasmtime::component::ComponentType>::Lower,));
781 
782                 unique_types.insert(ty);
783             } else {
784                 abi_list.extend(quote!(<() as wasmtime::component::ComponentType>::ABI,));
785                 case_names_and_checks.extend(match style {
786                     VariantStyle::Variant => {
787                         quote!((#name, <() as wasmtime::component::ComponentType>::typecheck),)
788                     }
789                     VariantStyle::Union => {
790                         quote!(<() as wasmtime::component::ComponentType>::typecheck,)
791                     }
792                     VariantStyle::Enum => quote!(#name,),
793                 });
794             }
795         }
796 
797         if lower_payload_case_declarations.is_empty() {
798             lower_payload_case_declarations.extend(quote!(_dummy: ()));
799         }
800 
801         let typecheck = match style {
802             VariantStyle::Variant => quote!(typecheck_variant),
803             VariantStyle::Union => quote!(typecheck_union),
804             VariantStyle::Enum => quote!(typecheck_enum),
805         };
806 
807         let generics = add_trait_bounds(generics, parse_quote!(wasmtime::component::ComponentType));
808         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
809         let lower = format_ident!("Lower{}", name);
810         let lower_payload = format_ident!("LowerPayload{}", name);
811 
812         // You may wonder why we make the types of all the fields of the #lower struct and #lower_payload union
813         // generic.  This is to work around a [normalization bug in
814         // rustc](https://github.com/rust-lang/rust/issues/90903) such that the compiler does not understand that
815         // e.g. `<i32 as ComponentType>::Lower` is `Copy` despite the bound specified in `ComponentType`'s
816         // definition.
817         //
818         // See also the comment in `Self::expand_record` above for another reason why we do this.
819 
820         let expanded = quote! {
821             #[doc(hidden)]
822             #[derive(Clone, Copy)]
823             #[repr(C)]
824             pub struct #lower<#lower_payload_generic_params> {
825                 tag: wasmtime::ValRaw,
826                 payload: #lower_payload<#lower_payload_generic_args>
827             }
828 
829             #[doc(hidden)]
830             #[allow(non_snake_case)]
831             #[derive(Clone, Copy)]
832             #[repr(C)]
833             union #lower_payload<#lower_payload_generic_params> {
834                 #lower_payload_case_declarations
835             }
836 
837             unsafe impl #impl_generics wasmtime::component::ComponentType for #name #ty_generics #where_clause {
838                 type Lower = #lower<#lower_generic_args>;
839 
840                 #[inline]
841                 fn typecheck(
842                     ty: &#internal::InterfaceType,
843                     types: &#internal::ComponentTypes,
844                 ) -> #internal::anyhow::Result<()> {
845                     #internal::#typecheck(ty, types, &[#case_names_and_checks])
846                 }
847 
848                 const ABI: #internal::CanonicalAbiInfo =
849                     #internal::CanonicalAbiInfo::variant_static(&[#abi_list]);
850             }
851 
852             unsafe impl #impl_generics #internal::ComponentVariant for #name #ty_generics #where_clause {
853                 const CASES: &'static [#internal::CanonicalAbiInfo] = &[#abi_list];
854             }
855         };
856 
857         Ok(quote!(const _: () = { #expanded };))
858     }
859 }
860 
861 #[derive(Debug)]
862 struct Flag {
863     rename: Option<String>,
864     name: String,
865 }
866 
867 impl Parse for Flag {
868     fn parse(input: ParseStream) -> Result<Self> {
869         let attributes = syn::Attribute::parse_outer(input)?;
870 
871         let rename = find_rename(&attributes)?
872             .map(|literal| {
873                 let s = literal.to_string();
874 
875                 s.strip_prefix('"')
876                     .and_then(|s| s.strip_suffix('"'))
877                     .map(|s| s.to_owned())
878                     .ok_or_else(|| Error::new(literal.span(), "expected string literal"))
879             })
880             .transpose()?;
881 
882         input.parse::<Token![const]>()?;
883         let name = input.parse::<syn::Ident>()?.to_string();
884 
885         Ok(Self { rename, name })
886     }
887 }
888 
889 #[derive(Debug)]
890 struct Flags {
891     name: String,
892     flags: Vec<Flag>,
893 }
894 
895 impl Parse for Flags {
896     fn parse(input: ParseStream) -> Result<Self> {
897         let name = input.parse::<syn::Ident>()?.to_string();
898 
899         let content;
900         braced!(content in input);
901 
902         let flags = content
903             .parse_terminated::<_, Token![;]>(Flag::parse)?
904             .into_iter()
905             .collect();
906 
907         Ok(Self { name, flags })
908     }
909 }
910 
911 #[proc_macro]
912 pub fn flags(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
913     expand_flags(&parse_macro_input!(input as Flags))
914         .unwrap_or_else(Error::into_compile_error)
915         .into()
916 }
917 
918 fn expand_flags(flags: &Flags) -> Result<TokenStream> {
919     let size = FlagsSize::from_count(flags.flags.len());
920 
921     let ty;
922     let eq;
923 
924     let count = flags.flags.len();
925 
926     match size {
927         FlagsSize::Size0 => {
928             ty = quote!(());
929             eq = quote!(true);
930         }
931         FlagsSize::Size1 => {
932             ty = quote!(u8);
933 
934             eq = if count == 8 {
935                 quote!(self.__inner0.eq(&rhs.__inner0))
936             } else {
937                 let mask = !(0xFF_u8 << count);
938 
939                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
940             };
941         }
942         FlagsSize::Size2 => {
943             ty = quote!(u16);
944 
945             eq = if count == 16 {
946                 quote!(self.__inner0.eq(&rhs.__inner0))
947             } else {
948                 let mask = !(0xFFFF_u16 << count);
949 
950                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
951             };
952         }
953         FlagsSize::Size4Plus(n) => {
954             ty = quote!(u32);
955 
956             let comparisons = (0..(n - 1))
957                 .map(|index| {
958                     let field = format_ident!("__inner{}", index);
959 
960                     quote!(self.#field.eq(&rhs.#field) &&)
961                 })
962                 .collect::<TokenStream>();
963 
964             let field = format_ident!("__inner{}", n - 1);
965 
966             eq = if count % 32 == 0 {
967                 quote!(#comparisons self.#field.eq(&rhs.#field))
968             } else {
969                 let mask = !(0xFFFF_FFFF_u32 << (count % 32));
970 
971                 quote!(#comparisons (self.#field & #mask).eq(&(rhs.#field & #mask)))
972             }
973         }
974     }
975 
976     let count;
977     let mut as_array;
978     let mut bitor;
979     let mut bitor_assign;
980     let mut bitand;
981     let mut bitand_assign;
982     let mut bitxor;
983     let mut bitxor_assign;
984     let mut not;
985 
986     match size {
987         FlagsSize::Size0 => {
988             count = 0;
989             as_array = quote!([]);
990             bitor = quote!(Self {});
991             bitor_assign = quote!();
992             bitand = quote!(Self {});
993             bitand_assign = quote!();
994             bitxor = quote!(Self {});
995             bitxor_assign = quote!();
996             not = quote!(Self {});
997         }
998         FlagsSize::Size1 | FlagsSize::Size2 => {
999             count = 1;
1000             as_array = quote!([self.__inner0 as u32]);
1001             bitor = quote!(Self {
1002                 __inner0: self.__inner0.bitor(rhs.__inner0)
1003             });
1004             bitor_assign = quote!(self.__inner0.bitor_assign(rhs.__inner0));
1005             bitand = quote!(Self {
1006                 __inner0: self.__inner0.bitand(rhs.__inner0)
1007             });
1008             bitand_assign = quote!(self.__inner0.bitand_assign(rhs.__inner0));
1009             bitxor = quote!(Self {
1010                 __inner0: self.__inner0.bitxor(rhs.__inner0)
1011             });
1012             bitxor_assign = quote!(self.__inner0.bitxor_assign(rhs.__inner0));
1013             not = quote!(Self {
1014                 __inner0: self.__inner0.not()
1015             });
1016         }
1017         FlagsSize::Size4Plus(n) => {
1018             count = n;
1019             as_array = TokenStream::new();
1020             bitor = TokenStream::new();
1021             bitor_assign = TokenStream::new();
1022             bitand = TokenStream::new();
1023             bitand_assign = TokenStream::new();
1024             bitxor = TokenStream::new();
1025             bitxor_assign = TokenStream::new();
1026             not = TokenStream::new();
1027 
1028             for index in 0..n {
1029                 let field = format_ident!("__inner{}", index);
1030 
1031                 as_array.extend(quote!(self.#field,));
1032                 bitor.extend(quote!(#field: self.#field.bitor(rhs.#field),));
1033                 bitor_assign.extend(quote!(self.#field.bitor_assign(rhs.#field);));
1034                 bitand.extend(quote!(#field: self.#field.bitand(rhs.#field),));
1035                 bitand_assign.extend(quote!(self.#field.bitand_assign(rhs.#field);));
1036                 bitxor.extend(quote!(#field: self.#field.bitxor(rhs.#field),));
1037                 bitxor_assign.extend(quote!(self.#field.bitxor_assign(rhs.#field);));
1038                 not.extend(quote!(#field: self.#field.not(),));
1039             }
1040 
1041             as_array = quote!([#as_array]);
1042             bitor = quote!(Self { #bitor });
1043             bitand = quote!(Self { #bitand });
1044             bitxor = quote!(Self { #bitxor });
1045             not = quote!(Self { #not });
1046         }
1047     };
1048 
1049     let name = format_ident!("{}", flags.name);
1050 
1051     let mut constants = TokenStream::new();
1052     let mut rust_names = TokenStream::new();
1053     let mut component_names = TokenStream::new();
1054 
1055     for (index, Flag { name, rename }) in flags.flags.iter().enumerate() {
1056         rust_names.extend(quote!(#name,));
1057 
1058         let component_name = rename.as_ref().unwrap_or(name);
1059         component_names.extend(quote!(#component_name,));
1060 
1061         let fields = match size {
1062             FlagsSize::Size0 => quote!(),
1063             FlagsSize::Size1 => {
1064                 let init = 1_u8 << index;
1065                 quote!(__inner0: #init)
1066             }
1067             FlagsSize::Size2 => {
1068                 let init = 1_u16 << index;
1069                 quote!(__inner0: #init)
1070             }
1071             FlagsSize::Size4Plus(n) => (0..n)
1072                 .map(|i| {
1073                     let field = format_ident!("__inner{}", i);
1074 
1075                     let init = if index / 32 == i {
1076                         1_u32 << (index % 32)
1077                     } else {
1078                         0
1079                     };
1080 
1081                     quote!(#field: #init,)
1082                 })
1083                 .collect::<TokenStream>(),
1084         };
1085 
1086         let name = format_ident!("{}", name);
1087 
1088         constants.extend(quote!(const #name: Self = Self { #fields };));
1089     }
1090 
1091     let generics = syn::Generics {
1092         lt_token: None,
1093         params: Punctuated::new(),
1094         gt_token: None,
1095         where_clause: None,
1096     };
1097 
1098     let fields = {
1099         let ty = syn::parse2::<syn::Type>(ty.clone())?;
1100 
1101         (0..count)
1102             .map(|index| syn::Field {
1103                 attrs: Vec::new(),
1104                 vis: syn::Visibility::Inherited,
1105                 ident: Some(format_ident!("__inner{}", index)),
1106                 colon_token: None,
1107                 ty: ty.clone(),
1108             })
1109             .collect::<Vec<_>>()
1110     };
1111 
1112     let fields = fields.iter().collect::<Vec<_>>();
1113 
1114     let component_type_impl = expand_record_for_component_type(
1115         &name,
1116         &generics,
1117         &fields,
1118         quote!(typecheck_flags),
1119         component_names,
1120     )?;
1121 
1122     let lower_impl = LowerExpander.expand_record(&name, &generics, &fields)?;
1123 
1124     let lift_impl = LiftExpander.expand_record(&name, &generics, &fields)?;
1125 
1126     let internal = quote!(wasmtime::component::__internal);
1127 
1128     let fields = fields
1129         .iter()
1130         .map(|syn::Field { ident, .. }| quote!(#[doc(hidden)] #ident: #ty,))
1131         .collect::<TokenStream>();
1132 
1133     let expanded = quote! {
1134         #[derive(Copy, Clone, Default)]
1135         struct #name { #fields }
1136 
1137         impl #name {
1138             #constants
1139 
1140             fn as_array(&self) -> [u32; #count] {
1141                 #as_array
1142             }
1143         }
1144 
1145         impl std::cmp::PartialEq for #name {
1146             fn eq(&self, rhs: &#name) -> bool {
1147                 #eq
1148             }
1149         }
1150 
1151         impl std::cmp::Eq for #name { }
1152 
1153         impl std::fmt::Debug for #name {
1154             fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1155                 #internal::format_flags(&self.as_array(), &[#rust_names], f)
1156             }
1157         }
1158 
1159         impl std::ops::BitOr for #name {
1160             type Output = #name;
1161 
1162             fn bitor(self, rhs: #name) -> #name {
1163                 #bitor
1164             }
1165         }
1166 
1167         impl std::ops::BitOrAssign for #name {
1168             fn bitor_assign(&mut self, rhs: #name) {
1169                 #bitor_assign
1170             }
1171         }
1172 
1173         impl std::ops::BitAnd for #name {
1174             type Output = #name;
1175 
1176             fn bitand(self, rhs: #name) -> #name {
1177                 #bitand
1178             }
1179         }
1180 
1181         impl std::ops::BitAndAssign for #name {
1182             fn bitand_assign(&mut self, rhs: #name) {
1183                 #bitand_assign
1184             }
1185         }
1186 
1187         impl std::ops::BitXor for #name {
1188             type Output = #name;
1189 
1190             fn bitxor(self, rhs: #name) -> #name {
1191                 #bitxor
1192             }
1193         }
1194 
1195         impl std::ops::BitXorAssign for #name {
1196             fn bitxor_assign(&mut self, rhs: #name) {
1197                 #bitxor_assign
1198             }
1199         }
1200 
1201         impl std::ops::Not for #name {
1202             type Output = #name;
1203 
1204             fn not(self) -> #name {
1205                 #not
1206             }
1207         }
1208 
1209         #component_type_impl
1210 
1211         #lower_impl
1212 
1213         #lift_impl
1214     };
1215 
1216     Ok(expanded)
1217 }
1218