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