144220746SAlex Crichton use proc_macro2::{Span, TokenStream};
22329ecc3SAlex Crichton use quote::{format_ident, quote};
32329ecc3SAlex Crichton use std::collections::HashSet;
42329ecc3SAlex Crichton use std::fmt;
52329ecc3SAlex Crichton use syn::parse::{Parse, ParseStream};
62329ecc3SAlex Crichton use syn::punctuated::Punctuated;
790ac295eSAlex Crichton use syn::{Data, DeriveInput, Error, Ident, Result, Token, braced, parse_quote};
82329ecc3SAlex Crichton use wasmtime_component_util::{DiscriminantSize, FlagsSize};
92329ecc3SAlex Crichton 
106d7bb360SAlex Crichton mod kw {
116d7bb360SAlex Crichton     syn::custom_keyword!(record);
126d7bb360SAlex Crichton     syn::custom_keyword!(variant);
136d7bb360SAlex Crichton     syn::custom_keyword!(flags);
146d7bb360SAlex Crichton     syn::custom_keyword!(name);
1544220746SAlex Crichton     syn::custom_keyword!(wasmtime_crate);
166d7bb360SAlex Crichton }
176d7bb360SAlex Crichton 
182329ecc3SAlex Crichton #[derive(Debug, Copy, Clone)]
192329ecc3SAlex Crichton enum Style {
202329ecc3SAlex Crichton     Record,
21fa41d131SAlex Crichton     Enum,
22fa41d131SAlex Crichton     Variant,
23fa41d131SAlex Crichton }
24fa41d131SAlex Crichton 
25fa41d131SAlex Crichton impl fmt::Display for Style {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result26fa41d131SAlex Crichton     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27fa41d131SAlex Crichton         match self {
28fa41d131SAlex Crichton             Style::Record => f.write_str("record"),
29fa41d131SAlex Crichton             Style::Enum => f.write_str("enum"),
30fa41d131SAlex Crichton             Style::Variant => f.write_str("variant"),
31fa41d131SAlex Crichton         }
32fa41d131SAlex Crichton     }
332329ecc3SAlex Crichton }
342329ecc3SAlex Crichton 
3544220746SAlex Crichton #[derive(Debug, Clone)]
3644220746SAlex Crichton enum ComponentAttr {
3744220746SAlex Crichton     Style(Style),
3844220746SAlex Crichton     WasmtimeCrate(syn::Path),
392329ecc3SAlex Crichton }
402329ecc3SAlex Crichton 
4144220746SAlex Crichton impl Parse for ComponentAttr {
parse(input: ParseStream) -> Result<Self>426d7bb360SAlex Crichton     fn parse(input: ParseStream) -> Result<Self> {
436d7bb360SAlex Crichton         let lookahead = input.lookahead1();
446d7bb360SAlex Crichton         if lookahead.peek(kw::record) {
456d7bb360SAlex Crichton             input.parse::<kw::record>()?;
4644220746SAlex Crichton             Ok(ComponentAttr::Style(Style::Record))
476d7bb360SAlex Crichton         } else if lookahead.peek(kw::variant) {
486d7bb360SAlex Crichton             input.parse::<kw::variant>()?;
49fa41d131SAlex Crichton             Ok(ComponentAttr::Style(Style::Variant))
506d7bb360SAlex Crichton         } else if lookahead.peek(Token![enum]) {
516d7bb360SAlex Crichton             input.parse::<Token![enum]>()?;
52fa41d131SAlex Crichton             Ok(ComponentAttr::Style(Style::Enum))
5344220746SAlex Crichton         } else if lookahead.peek(kw::wasmtime_crate) {
5444220746SAlex Crichton             input.parse::<kw::wasmtime_crate>()?;
5544220746SAlex Crichton             input.parse::<Token![=]>()?;
5644220746SAlex Crichton             Ok(ComponentAttr::WasmtimeCrate(input.parse()?))
576d7bb360SAlex Crichton         } else if input.peek(kw::flags) {
586d7bb360SAlex Crichton             Err(input.error(
596d7bb360SAlex Crichton                 "`flags` not allowed here; \
606d7bb360SAlex Crichton                  use `wasmtime::component::flags!` macro to define `flags` types",
616d7bb360SAlex Crichton             ))
626d7bb360SAlex Crichton         } else {
636d7bb360SAlex Crichton             Err(lookahead.error())
646d7bb360SAlex Crichton         }
656d7bb360SAlex Crichton     }
666d7bb360SAlex Crichton }
676d7bb360SAlex Crichton 
find_rename(attributes: &[syn::Attribute]) -> Result<Option<syn::LitStr>>686d7bb360SAlex Crichton fn find_rename(attributes: &[syn::Attribute]) -> Result<Option<syn::LitStr>> {
692329ecc3SAlex Crichton     let mut name = None;
702329ecc3SAlex Crichton 
712329ecc3SAlex Crichton     for attribute in attributes {
726d7bb360SAlex Crichton         if !attribute.path().is_ident("component") {
732329ecc3SAlex Crichton             continue;
742329ecc3SAlex Crichton         }
756d7bb360SAlex Crichton         let name_literal = attribute.parse_args_with(|parser: ParseStream<'_>| {
766d7bb360SAlex Crichton             parser.parse::<kw::name>()?;
776d7bb360SAlex Crichton             parser.parse::<Token![=]>()?;
786d7bb360SAlex Crichton             parser.parse::<syn::LitStr>()
796d7bb360SAlex Crichton         })?;
802329ecc3SAlex Crichton 
812329ecc3SAlex Crichton         if name.is_some() {
826d7bb360SAlex Crichton             return Err(Error::new_spanned(
836d7bb360SAlex Crichton                 attribute,
846d7bb360SAlex Crichton                 "duplicate field rename attribute",
856d7bb360SAlex Crichton             ));
862329ecc3SAlex Crichton         }
872329ecc3SAlex Crichton 
882329ecc3SAlex Crichton         name = Some(name_literal);
892329ecc3SAlex Crichton     }
902329ecc3SAlex Crichton 
912329ecc3SAlex Crichton     Ok(name)
922329ecc3SAlex Crichton }
932329ecc3SAlex Crichton 
add_trait_bounds(generics: &syn::Generics, bound: syn::TypeParamBound) -> syn::Generics942329ecc3SAlex Crichton fn add_trait_bounds(generics: &syn::Generics, bound: syn::TypeParamBound) -> syn::Generics {
952329ecc3SAlex Crichton     let mut generics = generics.clone();
962329ecc3SAlex Crichton     for param in &mut generics.params {
972329ecc3SAlex Crichton         if let syn::GenericParam::Type(ref mut type_param) = *param {
982329ecc3SAlex Crichton             type_param.bounds.push(bound.clone());
992329ecc3SAlex Crichton         }
1002329ecc3SAlex Crichton     }
1012329ecc3SAlex Crichton     generics
1022329ecc3SAlex Crichton }
1032329ecc3SAlex Crichton 
1042329ecc3SAlex Crichton pub struct VariantCase<'a> {
1052329ecc3SAlex Crichton     attrs: &'a [syn::Attribute],
1062329ecc3SAlex Crichton     ident: &'a syn::Ident,
1072329ecc3SAlex Crichton     ty: Option<&'a syn::Type>,
1082329ecc3SAlex Crichton }
1092329ecc3SAlex Crichton 
1102329ecc3SAlex Crichton pub trait Expander {
expand_record( &self, name: &syn::Ident, generics: &syn::Generics, fields: &[&syn::Field], wasmtime_crate: &syn::Path, ) -> Result<TokenStream>1112329ecc3SAlex Crichton     fn expand_record(
1122329ecc3SAlex Crichton         &self,
1132329ecc3SAlex Crichton         name: &syn::Ident,
1142329ecc3SAlex Crichton         generics: &syn::Generics,
1152329ecc3SAlex Crichton         fields: &[&syn::Field],
11644220746SAlex Crichton         wasmtime_crate: &syn::Path,
1172329ecc3SAlex Crichton     ) -> Result<TokenStream>;
1182329ecc3SAlex Crichton 
expand_variant( &self, name: &syn::Ident, generics: &syn::Generics, discriminant_size: DiscriminantSize, cases: &[VariantCase], wasmtime_crate: &syn::Path, ) -> Result<TokenStream>1192329ecc3SAlex Crichton     fn expand_variant(
1202329ecc3SAlex Crichton         &self,
1212329ecc3SAlex Crichton         name: &syn::Ident,
1222329ecc3SAlex Crichton         generics: &syn::Generics,
1232329ecc3SAlex Crichton         discriminant_size: DiscriminantSize,
1242329ecc3SAlex Crichton         cases: &[VariantCase],
125fa41d131SAlex Crichton         wasmtime_crate: &syn::Path,
126fa41d131SAlex Crichton     ) -> Result<TokenStream>;
127fa41d131SAlex Crichton 
expand_enum( &self, name: &syn::Ident, discriminant_size: DiscriminantSize, cases: &[VariantCase], wasmtime_crate: &syn::Path, ) -> Result<TokenStream>128fa41d131SAlex Crichton     fn expand_enum(
129fa41d131SAlex Crichton         &self,
130fa41d131SAlex Crichton         name: &syn::Ident,
131fa41d131SAlex Crichton         discriminant_size: DiscriminantSize,
132fa41d131SAlex Crichton         cases: &[VariantCase],
13344220746SAlex Crichton         wasmtime_crate: &syn::Path,
1342329ecc3SAlex Crichton     ) -> Result<TokenStream>;
1352329ecc3SAlex Crichton }
1362329ecc3SAlex Crichton 
expand(expander: &dyn Expander, input: &DeriveInput) -> Result<TokenStream>1372329ecc3SAlex Crichton pub fn expand(expander: &dyn Expander, input: &DeriveInput) -> Result<TokenStream> {
13844220746SAlex Crichton     let mut wasmtime_crate = None;
13944220746SAlex Crichton     let mut style = None;
14044220746SAlex Crichton 
14144220746SAlex Crichton     for attribute in &input.attrs {
14244220746SAlex Crichton         if !attribute.path().is_ident("component") {
14344220746SAlex Crichton             continue;
14444220746SAlex Crichton         }
14544220746SAlex Crichton         match attribute.parse_args()? {
14644220746SAlex Crichton             ComponentAttr::WasmtimeCrate(c) => wasmtime_crate = Some(c),
14744220746SAlex Crichton             ComponentAttr::Style(attr_style) => {
14844220746SAlex Crichton                 if style.is_some() {
14944220746SAlex Crichton                     return Err(Error::new_spanned(
15044220746SAlex Crichton                         attribute,
15144220746SAlex Crichton                         "duplicate `component` attribute",
15244220746SAlex Crichton                     ));
15344220746SAlex Crichton                 }
15444220746SAlex Crichton                 style = Some(attr_style);
15544220746SAlex Crichton             }
1562329ecc3SAlex Crichton         }
1572329ecc3SAlex Crichton     }
1582329ecc3SAlex Crichton 
15944220746SAlex Crichton     let style = style.ok_or_else(|| Error::new_spanned(input, "missing `component` attribute"))?;
16044220746SAlex Crichton     let wasmtime_crate = wasmtime_crate.unwrap_or_else(default_wasmtime_crate);
16144220746SAlex Crichton     match style {
16244220746SAlex Crichton         Style::Record => expand_record(expander, input, &wasmtime_crate),
163fa41d131SAlex Crichton         Style::Enum | Style::Variant => expand_variant(expander, input, style, &wasmtime_crate),
16444220746SAlex Crichton     }
16544220746SAlex Crichton }
16644220746SAlex Crichton 
default_wasmtime_crate() -> syn::Path16744220746SAlex Crichton fn default_wasmtime_crate() -> syn::Path {
16844220746SAlex Crichton     Ident::new("wasmtime", Span::call_site()).into()
16944220746SAlex Crichton }
17044220746SAlex Crichton 
expand_record( expander: &dyn Expander, input: &DeriveInput, wasmtime_crate: &syn::Path, ) -> Result<TokenStream>17144220746SAlex Crichton fn expand_record(
17244220746SAlex Crichton     expander: &dyn Expander,
17344220746SAlex Crichton     input: &DeriveInput,
17444220746SAlex Crichton     wasmtime_crate: &syn::Path,
17544220746SAlex Crichton ) -> Result<TokenStream> {
1762329ecc3SAlex Crichton     let name = &input.ident;
1772329ecc3SAlex Crichton 
1782329ecc3SAlex Crichton     let body = if let Data::Struct(body) = &input.data {
1792329ecc3SAlex Crichton         body
1802329ecc3SAlex Crichton     } else {
1812329ecc3SAlex Crichton         return Err(Error::new(
1822329ecc3SAlex Crichton             name.span(),
1832329ecc3SAlex Crichton             "`record` component types can only be derived for Rust `struct`s",
1842329ecc3SAlex Crichton         ));
1852329ecc3SAlex Crichton     };
1862329ecc3SAlex Crichton 
1872329ecc3SAlex Crichton     match &body.fields {
1882329ecc3SAlex Crichton         syn::Fields::Named(fields) => expander.expand_record(
1892329ecc3SAlex Crichton             &input.ident,
1902329ecc3SAlex Crichton             &input.generics,
1912329ecc3SAlex Crichton             &fields.named.iter().collect::<Vec<_>>(),
19244220746SAlex Crichton             wasmtime_crate,
1932329ecc3SAlex Crichton         ),
1942329ecc3SAlex Crichton 
1952329ecc3SAlex Crichton         syn::Fields::Unnamed(_) | syn::Fields::Unit => Err(Error::new(
1962329ecc3SAlex Crichton             name.span(),
1972329ecc3SAlex Crichton             "`record` component types can only be derived for `struct`s with named fields",
1982329ecc3SAlex Crichton         )),
1992329ecc3SAlex Crichton     }
2002329ecc3SAlex Crichton }
2012329ecc3SAlex Crichton 
expand_variant( expander: &dyn Expander, input: &DeriveInput, style: Style, wasmtime_crate: &syn::Path, ) -> Result<TokenStream>2022329ecc3SAlex Crichton fn expand_variant(
2032329ecc3SAlex Crichton     expander: &dyn Expander,
2042329ecc3SAlex Crichton     input: &DeriveInput,
205fa41d131SAlex Crichton     style: Style,
20644220746SAlex Crichton     wasmtime_crate: &syn::Path,
2072329ecc3SAlex Crichton ) -> Result<TokenStream> {
2082329ecc3SAlex Crichton     let name = &input.ident;
2092329ecc3SAlex Crichton 
2102329ecc3SAlex Crichton     let body = if let Data::Enum(body) = &input.data {
2112329ecc3SAlex Crichton         body
2122329ecc3SAlex Crichton     } else {
2132329ecc3SAlex Crichton         return Err(Error::new(
2142329ecc3SAlex Crichton             name.span(),
215a0442ea0SHamir Mahal             format!("`{style}` component types can only be derived for Rust `enum`s"),
2162329ecc3SAlex Crichton         ));
2172329ecc3SAlex Crichton     };
2182329ecc3SAlex Crichton 
2192329ecc3SAlex Crichton     if body.variants.is_empty() {
2202329ecc3SAlex Crichton         return Err(Error::new(
2212329ecc3SAlex Crichton             name.span(),
22290ac295eSAlex Crichton             format!(
22390ac295eSAlex Crichton                 "`{style}` component types can only be derived for Rust `enum`s with at least one variant"
22490ac295eSAlex Crichton             ),
2252329ecc3SAlex Crichton         ));
2262329ecc3SAlex Crichton     }
2272329ecc3SAlex Crichton 
2282329ecc3SAlex Crichton     let discriminant_size = DiscriminantSize::from_count(body.variants.len()).ok_or_else(|| {
2292329ecc3SAlex Crichton         Error::new(
2302329ecc3SAlex Crichton             input.ident.span(),
2312329ecc3SAlex Crichton             "`enum`s with more than 2^32 variants are not supported",
2322329ecc3SAlex Crichton         )
2332329ecc3SAlex Crichton     })?;
2342329ecc3SAlex Crichton 
2352329ecc3SAlex Crichton     let cases = body
2362329ecc3SAlex Crichton         .variants
2372329ecc3SAlex Crichton         .iter()
2382329ecc3SAlex Crichton         .map(
2392329ecc3SAlex Crichton             |syn::Variant {
2402329ecc3SAlex Crichton                  attrs,
2412329ecc3SAlex Crichton                  ident,
2422329ecc3SAlex Crichton                  fields,
2432329ecc3SAlex Crichton                  ..
2442329ecc3SAlex Crichton              }| {
2452329ecc3SAlex Crichton                 Ok(VariantCase {
2462329ecc3SAlex Crichton                     attrs,
2472329ecc3SAlex Crichton                     ident,
2482329ecc3SAlex Crichton                     ty: match fields {
2492329ecc3SAlex Crichton                         syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
2502329ecc3SAlex Crichton                             Some(&fields.unnamed[0].ty)
2512329ecc3SAlex Crichton                         }
2522329ecc3SAlex Crichton                         syn::Fields::Unit => None,
2532329ecc3SAlex Crichton                         _ => {
2542329ecc3SAlex Crichton                             return Err(Error::new(
2552329ecc3SAlex Crichton                                 name.span(),
2562329ecc3SAlex Crichton                                 format!(
2572329ecc3SAlex Crichton                                     "`{}` component types can only be derived for Rust `enum`s \
2582329ecc3SAlex Crichton                                      containing variants with {}",
2592329ecc3SAlex Crichton                                     style,
2602329ecc3SAlex Crichton                                     match style {
261fa41d131SAlex Crichton                                         Style::Variant => "at most one unnamed field each",
262fa41d131SAlex Crichton                                         Style::Enum => "no fields",
263fa41d131SAlex Crichton                                         Style::Record => unreachable!(),
2642329ecc3SAlex Crichton                                     }
2652329ecc3SAlex Crichton                                 ),
26690ac295eSAlex Crichton                             ));
2672329ecc3SAlex Crichton                         }
2682329ecc3SAlex Crichton                     },
2692329ecc3SAlex Crichton                 })
2702329ecc3SAlex Crichton             },
2712329ecc3SAlex Crichton         )
2722329ecc3SAlex Crichton         .collect::<Result<Vec<_>>>()?;
2732329ecc3SAlex Crichton 
274fa41d131SAlex Crichton     match style {
275fa41d131SAlex Crichton         Style::Variant => expander.expand_variant(
2762329ecc3SAlex Crichton             &input.ident,
2772329ecc3SAlex Crichton             &input.generics,
2782329ecc3SAlex Crichton             discriminant_size,
2792329ecc3SAlex Crichton             &cases,
28044220746SAlex Crichton             wasmtime_crate,
281fa41d131SAlex Crichton         ),
282fa41d131SAlex Crichton         Style::Enum => {
283fa41d131SAlex Crichton             validate_enum(input, &body, discriminant_size)?;
284fa41d131SAlex Crichton             expander.expand_enum(&input.ident, discriminant_size, &cases, wasmtime_crate)
285fa41d131SAlex Crichton         }
286fa41d131SAlex Crichton         Style::Record => unreachable!(),
287fa41d131SAlex Crichton     }
288fa41d131SAlex Crichton }
289fa41d131SAlex Crichton 
290fa41d131SAlex Crichton /// Validates component model `enum` definitions are accompanied with
291fa41d131SAlex Crichton /// appropriate `#[repr]` tags. Additionally requires that no discriminants are
292fa41d131SAlex Crichton /// listed to ensure that unsafe transmutes in lift are valid.
validate_enum(input: &DeriveInput, body: &syn::DataEnum, size: DiscriminantSize) -> Result<()>293fa41d131SAlex Crichton fn validate_enum(input: &DeriveInput, body: &syn::DataEnum, size: DiscriminantSize) -> Result<()> {
294fa41d131SAlex Crichton     if !input.generics.params.is_empty() {
295fa41d131SAlex Crichton         return Err(Error::new_spanned(
296fa41d131SAlex Crichton             &input.generics.params,
297fa41d131SAlex Crichton             "cannot have generics on an `enum`",
298fa41d131SAlex Crichton         ));
299fa41d131SAlex Crichton     }
300fa41d131SAlex Crichton     if let Some(clause) = &input.generics.where_clause {
301fa41d131SAlex Crichton         return Err(Error::new_spanned(
302fa41d131SAlex Crichton             clause,
303fa41d131SAlex Crichton             "cannot have a where clause on an `enum`",
304fa41d131SAlex Crichton         ));
305fa41d131SAlex Crichton     }
306fa41d131SAlex Crichton     let expected_discr = match size {
307fa41d131SAlex Crichton         DiscriminantSize::Size1 => "u8",
308fa41d131SAlex Crichton         DiscriminantSize::Size2 => "u16",
309fa41d131SAlex Crichton         DiscriminantSize::Size4 => "u32",
310fa41d131SAlex Crichton     };
311fa41d131SAlex Crichton     let mut found_repr = false;
312fa41d131SAlex Crichton     for attr in input.attrs.iter() {
313fa41d131SAlex Crichton         if !attr.meta.path().is_ident("repr") {
314fa41d131SAlex Crichton             continue;
315fa41d131SAlex Crichton         }
316fa41d131SAlex Crichton         let list = attr.meta.require_list()?;
317fa41d131SAlex Crichton         found_repr = true;
318fa41d131SAlex Crichton         if list.tokens.to_string() != expected_discr {
319fa41d131SAlex Crichton             return Err(Error::new_spanned(
320fa41d131SAlex Crichton                 &list.tokens,
321fa41d131SAlex Crichton                 format!(
322fa41d131SAlex Crichton                     "expected `repr({expected_discr})`, found `repr({})`",
323fa41d131SAlex Crichton                     list.tokens
324fa41d131SAlex Crichton                 ),
325fa41d131SAlex Crichton             ));
326fa41d131SAlex Crichton         }
327fa41d131SAlex Crichton     }
328fa41d131SAlex Crichton     if !found_repr {
329fa41d131SAlex Crichton         return Err(Error::new_spanned(
330fa41d131SAlex Crichton             &body.enum_token,
331fa41d131SAlex Crichton             format!("missing required `#[repr({expected_discr})]`"),
332fa41d131SAlex Crichton         ));
333fa41d131SAlex Crichton     }
334fa41d131SAlex Crichton 
335fa41d131SAlex Crichton     for case in body.variants.iter() {
336fa41d131SAlex Crichton         if let Some((_, expr)) = &case.discriminant {
337fa41d131SAlex Crichton             return Err(Error::new_spanned(
338fa41d131SAlex Crichton                 expr,
339fa41d131SAlex Crichton                 "cannot have an explicit discriminant",
340fa41d131SAlex Crichton             ));
341fa41d131SAlex Crichton         }
342fa41d131SAlex Crichton     }
343fa41d131SAlex Crichton 
344fa41d131SAlex Crichton     Ok(())
3452329ecc3SAlex Crichton }
3462329ecc3SAlex Crichton 
expand_record_for_component_type( name: &syn::Ident, generics: &syn::Generics, fields: &[&syn::Field], typecheck: TokenStream, typecheck_argument: TokenStream, wt: &syn::Path, ) -> Result<TokenStream>3472329ecc3SAlex Crichton fn expand_record_for_component_type(
3482329ecc3SAlex Crichton     name: &syn::Ident,
3492329ecc3SAlex Crichton     generics: &syn::Generics,
3502329ecc3SAlex Crichton     fields: &[&syn::Field],
3512329ecc3SAlex Crichton     typecheck: TokenStream,
3522329ecc3SAlex Crichton     typecheck_argument: TokenStream,
35344220746SAlex Crichton     wt: &syn::Path,
3542329ecc3SAlex Crichton ) -> Result<TokenStream> {
35544220746SAlex Crichton     let internal = quote!(#wt::component::__internal);
3562329ecc3SAlex Crichton 
3572329ecc3SAlex Crichton     let mut lower_generic_params = TokenStream::new();
3582329ecc3SAlex Crichton     let mut lower_generic_args = TokenStream::new();
3592329ecc3SAlex Crichton     let mut lower_field_declarations = TokenStream::new();
3602329ecc3SAlex Crichton     let mut abi_list = TokenStream::new();
3612329ecc3SAlex Crichton     let mut unique_types = HashSet::new();
3622329ecc3SAlex Crichton 
3632329ecc3SAlex Crichton     for (index, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
3642329ecc3SAlex Crichton         let generic = format_ident!("T{}", index);
3652329ecc3SAlex Crichton 
3662329ecc3SAlex Crichton         lower_generic_params.extend(quote!(#generic: Copy,));
36744220746SAlex Crichton         lower_generic_args.extend(quote!(<#ty as #wt::component::ComponentType>::Lower,));
3682329ecc3SAlex Crichton 
3692329ecc3SAlex Crichton         lower_field_declarations.extend(quote!(#ident: #generic,));
3702329ecc3SAlex Crichton 
3712329ecc3SAlex Crichton         abi_list.extend(quote!(
37244220746SAlex Crichton             <#ty as #wt::component::ComponentType>::ABI,
3732329ecc3SAlex Crichton         ));
3742329ecc3SAlex Crichton 
3752329ecc3SAlex Crichton         unique_types.insert(ty);
3762329ecc3SAlex Crichton     }
3772329ecc3SAlex Crichton 
37844220746SAlex Crichton     let generics = add_trait_bounds(generics, parse_quote!(#wt::component::ComponentType));
3792329ecc3SAlex Crichton     let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
3802329ecc3SAlex Crichton     let lower = format_ident!("Lower{}", name);
3812329ecc3SAlex Crichton 
3822329ecc3SAlex Crichton     // You may wonder why we make the types of all the fields of the #lower struct generic.  This is to work
3832329ecc3SAlex Crichton     // around the lack of [perfect derive support in
3842329ecc3SAlex Crichton     // rustc](https://smallcultfollowing.com/babysteps//blog/2022/04/12/implied-bounds-and-perfect-derive/#what-is-perfect-derive)
3852329ecc3SAlex Crichton     // as of this writing.
3862329ecc3SAlex Crichton     //
3872329ecc3SAlex Crichton     // If the struct we're deriving a `ComponentType` impl for has any generic parameters, then #lower needs
3882329ecc3SAlex Crichton     // generic parameters too.  And if we just copy the parameters and bounds from the impl to #lower, then the
3892329ecc3SAlex Crichton     // `#[derive(Clone, Copy)]` will fail unless the original generics were declared with those bounds, which
3902329ecc3SAlex Crichton     // we don't want to require.
3912329ecc3SAlex Crichton     //
3922329ecc3SAlex Crichton     // Alternatively, we could just pass the `Lower` associated type of each generic type as arguments to
3932329ecc3SAlex Crichton     // #lower, but that would require distinguishing between generic and concrete types when generating
3942329ecc3SAlex Crichton     // #lower_field_declarations, which would require some form of symbol resolution.  That doesn't seem worth
3952329ecc3SAlex Crichton     // the trouble.
3962329ecc3SAlex Crichton 
3972329ecc3SAlex Crichton     let expanded = quote! {
3982329ecc3SAlex Crichton         #[doc(hidden)]
3992329ecc3SAlex Crichton         #[derive(Clone, Copy)]
4002329ecc3SAlex Crichton         #[repr(C)]
4012329ecc3SAlex Crichton         pub struct #lower <#lower_generic_params> {
4022329ecc3SAlex Crichton             #lower_field_declarations
40344220746SAlex Crichton             _align: [#wt::ValRaw; 0],
4042329ecc3SAlex Crichton         }
4052329ecc3SAlex Crichton 
40644220746SAlex Crichton         unsafe impl #impl_generics #wt::component::ComponentType for #name #ty_generics #where_clause {
4072329ecc3SAlex Crichton             type Lower = #lower <#lower_generic_args>;
4082329ecc3SAlex Crichton 
4092329ecc3SAlex Crichton             const ABI: #internal::CanonicalAbiInfo =
4102329ecc3SAlex Crichton                 #internal::CanonicalAbiInfo::record_static(&[#abi_list]);
4112329ecc3SAlex Crichton 
4122329ecc3SAlex Crichton             #[inline]
4132329ecc3SAlex Crichton             fn typecheck(
4142329ecc3SAlex Crichton                 ty: &#internal::InterfaceType,
4155a6ed0fbSAlex Crichton                 types: &#internal::InstanceType<'_>,
416*96e19700SNick Fitzgerald             ) -> #wt::Result<()> {
4172329ecc3SAlex Crichton                 #internal::#typecheck(ty, types, &[#typecheck_argument])
4182329ecc3SAlex Crichton             }
4192329ecc3SAlex Crichton         }
4202329ecc3SAlex Crichton     };
4212329ecc3SAlex Crichton 
4222329ecc3SAlex Crichton     Ok(quote!(const _: () = { #expanded };))
4232329ecc3SAlex Crichton }
4242329ecc3SAlex Crichton 
quote(size: DiscriminantSize, discriminant: usize) -> TokenStream4252329ecc3SAlex Crichton fn quote(size: DiscriminantSize, discriminant: usize) -> TokenStream {
4262329ecc3SAlex Crichton     match size {
4272329ecc3SAlex Crichton         DiscriminantSize::Size1 => {
4282329ecc3SAlex Crichton             let discriminant = u8::try_from(discriminant).unwrap();
4292329ecc3SAlex Crichton             quote!(#discriminant)
4302329ecc3SAlex Crichton         }
4312329ecc3SAlex Crichton         DiscriminantSize::Size2 => {
4322329ecc3SAlex Crichton             let discriminant = u16::try_from(discriminant).unwrap();
4332329ecc3SAlex Crichton             quote!(#discriminant)
4342329ecc3SAlex Crichton         }
4352329ecc3SAlex Crichton         DiscriminantSize::Size4 => {
4362329ecc3SAlex Crichton             let discriminant = u32::try_from(discriminant).unwrap();
4372329ecc3SAlex Crichton             quote!(#discriminant)
4382329ecc3SAlex Crichton         }
4392329ecc3SAlex Crichton     }
4402329ecc3SAlex Crichton }
4412329ecc3SAlex Crichton 
4422329ecc3SAlex Crichton pub struct LiftExpander;
4432329ecc3SAlex Crichton 
4442329ecc3SAlex Crichton impl Expander for LiftExpander {
expand_record( &self, name: &syn::Ident, generics: &syn::Generics, fields: &[&syn::Field], wt: &syn::Path, ) -> Result<TokenStream>4452329ecc3SAlex Crichton     fn expand_record(
4462329ecc3SAlex Crichton         &self,
4472329ecc3SAlex Crichton         name: &syn::Ident,
4482329ecc3SAlex Crichton         generics: &syn::Generics,
4492329ecc3SAlex Crichton         fields: &[&syn::Field],
45044220746SAlex Crichton         wt: &syn::Path,
4512329ecc3SAlex Crichton     ) -> Result<TokenStream> {
45244220746SAlex Crichton         let internal = quote!(#wt::component::__internal);
4532329ecc3SAlex Crichton 
4542329ecc3SAlex Crichton         let mut lifts = TokenStream::new();
4552329ecc3SAlex Crichton         let mut loads = TokenStream::new();
4562329ecc3SAlex Crichton 
457e8f4f862SAlex Crichton         for (i, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
458e8f4f862SAlex Crichton             let field_ty = quote!(ty.fields[#i].ty);
4597dba8efdSNick Fitzgerald             lifts.extend(
4607dba8efdSNick Fitzgerald                 quote!(#ident: <#ty as #wt::component::Lift>::linear_lift_from_flat(
461e8f4f862SAlex Crichton                 cx, #field_ty, &src.#ident
4627dba8efdSNick Fitzgerald             )?,),
4637dba8efdSNick Fitzgerald             );
4642329ecc3SAlex Crichton 
4657dba8efdSNick Fitzgerald             loads.extend(
4667dba8efdSNick Fitzgerald                 quote!(#ident: <#ty as #wt::component::Lift>::linear_lift_from_memory(
467e8f4f862SAlex Crichton                 cx, #field_ty,
4682329ecc3SAlex Crichton                 &bytes
46944220746SAlex Crichton                     [<#ty as #wt::component::ComponentType>::ABI.next_field32_size(&mut offset)..]
47044220746SAlex Crichton                     [..<#ty as #wt::component::ComponentType>::SIZE32]
4717dba8efdSNick Fitzgerald             )?,),
4727dba8efdSNick Fitzgerald             );
4732329ecc3SAlex Crichton         }
4742329ecc3SAlex Crichton 
47544220746SAlex Crichton         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lift));
4762329ecc3SAlex Crichton         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
4772329ecc3SAlex Crichton 
478e8f4f862SAlex Crichton         let extract_ty = quote! {
479e8f4f862SAlex Crichton             let ty = match ty {
480e8f4f862SAlex Crichton                 #internal::InterfaceType::Record(i) => &cx.types[i],
481e8f4f862SAlex Crichton                 _ => #internal::bad_type_info(),
482e8f4f862SAlex Crichton             };
483e8f4f862SAlex Crichton         };
484e8f4f862SAlex Crichton 
4852329ecc3SAlex Crichton         let expanded = quote! {
48644220746SAlex Crichton             unsafe impl #impl_generics #wt::component::Lift for #name #ty_generics #where_clause {
4872329ecc3SAlex Crichton                 #[inline]
4887dba8efdSNick Fitzgerald                 fn linear_lift_from_flat(
4895a6ed0fbSAlex Crichton                     cx: &mut #internal::LiftContext<'_>,
490e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
4912329ecc3SAlex Crichton                     src: &Self::Lower,
492*96e19700SNick Fitzgerald                 ) -> #wt::Result<Self> {
493e8f4f862SAlex Crichton                     #extract_ty
4942329ecc3SAlex Crichton                     Ok(Self {
4952329ecc3SAlex Crichton                         #lifts
4962329ecc3SAlex Crichton                     })
4972329ecc3SAlex Crichton                 }
4982329ecc3SAlex Crichton 
4992329ecc3SAlex Crichton                 #[inline]
5007dba8efdSNick Fitzgerald                 fn linear_lift_from_memory(
5015a6ed0fbSAlex Crichton                     cx: &mut #internal::LiftContext<'_>,
502e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
503e8f4f862SAlex Crichton                     bytes: &[u8],
504*96e19700SNick Fitzgerald                 ) -> #wt::Result<Self> {
505e8f4f862SAlex Crichton                     #extract_ty
5062329ecc3SAlex Crichton                     debug_assert!(
5072329ecc3SAlex Crichton                         (bytes.as_ptr() as usize)
50844220746SAlex Crichton                             % (<Self as #wt::component::ComponentType>::ALIGN32 as usize)
5092329ecc3SAlex Crichton                             == 0
5102329ecc3SAlex Crichton                     );
5112329ecc3SAlex Crichton                     let mut offset = 0;
5122329ecc3SAlex Crichton                     Ok(Self {
5132329ecc3SAlex Crichton                         #loads
5142329ecc3SAlex Crichton                     })
5152329ecc3SAlex Crichton                 }
5162329ecc3SAlex Crichton             }
5172329ecc3SAlex Crichton         };
5182329ecc3SAlex Crichton 
5192329ecc3SAlex Crichton         Ok(expanded)
5202329ecc3SAlex Crichton     }
5212329ecc3SAlex Crichton 
expand_variant( &self, name: &syn::Ident, generics: &syn::Generics, discriminant_size: DiscriminantSize, cases: &[VariantCase], wt: &syn::Path, ) -> Result<TokenStream>5222329ecc3SAlex Crichton     fn expand_variant(
5232329ecc3SAlex Crichton         &self,
5242329ecc3SAlex Crichton         name: &syn::Ident,
5252329ecc3SAlex Crichton         generics: &syn::Generics,
5262329ecc3SAlex Crichton         discriminant_size: DiscriminantSize,
5272329ecc3SAlex Crichton         cases: &[VariantCase],
52844220746SAlex Crichton         wt: &syn::Path,
5292329ecc3SAlex Crichton     ) -> Result<TokenStream> {
53044220746SAlex Crichton         let internal = quote!(#wt::component::__internal);
5312329ecc3SAlex Crichton 
5322329ecc3SAlex Crichton         let mut lifts = TokenStream::new();
5332329ecc3SAlex Crichton         let mut loads = TokenStream::new();
5342329ecc3SAlex Crichton 
5352329ecc3SAlex Crichton         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
5362329ecc3SAlex Crichton             let index_u32 = u32::try_from(index).unwrap();
5372329ecc3SAlex Crichton 
5382329ecc3SAlex Crichton             let index_quoted = quote(discriminant_size, index);
5392329ecc3SAlex Crichton 
5402329ecc3SAlex Crichton             if let Some(ty) = ty {
541fa41d131SAlex Crichton                 let payload_ty = quote!(ty.cases[#index].unwrap_or_else(#internal::bad_type_info));
5422329ecc3SAlex Crichton                 lifts.extend(
5437dba8efdSNick Fitzgerald                     quote!(#index_u32 => Self::#ident(<#ty as #wt::component::Lift>::linear_lift_from_flat(
544e8f4f862SAlex Crichton                         cx, #payload_ty, unsafe { &src.payload.#ident }
5452329ecc3SAlex Crichton                     )?),),
5462329ecc3SAlex Crichton                 );
5472329ecc3SAlex Crichton 
5482329ecc3SAlex Crichton                 loads.extend(
5497dba8efdSNick Fitzgerald                     quote!(#index_quoted => Self::#ident(<#ty as #wt::component::Lift>::linear_lift_from_memory(
55044220746SAlex Crichton                         cx, #payload_ty, &payload[..<#ty as #wt::component::ComponentType>::SIZE32]
5512329ecc3SAlex Crichton                     )?),),
5522329ecc3SAlex Crichton                 );
5532329ecc3SAlex Crichton             } else {
5542329ecc3SAlex Crichton                 lifts.extend(quote!(#index_u32 => Self::#ident,));
5552329ecc3SAlex Crichton 
5562329ecc3SAlex Crichton                 loads.extend(quote!(#index_quoted => Self::#ident,));
5572329ecc3SAlex Crichton             }
5582329ecc3SAlex Crichton         }
5592329ecc3SAlex Crichton 
56044220746SAlex Crichton         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lift));
5612329ecc3SAlex Crichton         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
5622329ecc3SAlex Crichton 
5632329ecc3SAlex Crichton         let from_bytes = match discriminant_size {
5642329ecc3SAlex Crichton             DiscriminantSize::Size1 => quote!(bytes[0]),
5652329ecc3SAlex Crichton             DiscriminantSize::Size2 => quote!(u16::from_le_bytes(bytes[0..2].try_into()?)),
5662329ecc3SAlex Crichton             DiscriminantSize::Size4 => quote!(u32::from_le_bytes(bytes[0..4].try_into()?)),
5672329ecc3SAlex Crichton         };
5682329ecc3SAlex Crichton 
569e8f4f862SAlex Crichton         let extract_ty = quote! {
570e8f4f862SAlex Crichton             let ty = match ty {
571fa41d131SAlex Crichton                 #internal::InterfaceType::Variant(i) => &cx.types[i],
572e8f4f862SAlex Crichton                 _ => #internal::bad_type_info(),
573e8f4f862SAlex Crichton             };
574e8f4f862SAlex Crichton         };
575e8f4f862SAlex Crichton 
5762329ecc3SAlex Crichton         let expanded = quote! {
57744220746SAlex Crichton             unsafe impl #impl_generics #wt::component::Lift for #name #ty_generics #where_clause {
5782329ecc3SAlex Crichton                 #[inline]
5797dba8efdSNick Fitzgerald                 fn linear_lift_from_flat(
5805a6ed0fbSAlex Crichton                     cx: &mut #internal::LiftContext<'_>,
581e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
5822329ecc3SAlex Crichton                     src: &Self::Lower,
583*96e19700SNick Fitzgerald                 ) -> #wt::Result<Self> {
584e8f4f862SAlex Crichton                     #extract_ty
5852329ecc3SAlex Crichton                     Ok(match src.tag.get_u32() {
5862329ecc3SAlex Crichton                         #lifts
587*96e19700SNick Fitzgerald                         discrim => #wt::bail!("unexpected discriminant: {}", discrim),
5882329ecc3SAlex Crichton                     })
5892329ecc3SAlex Crichton                 }
5902329ecc3SAlex Crichton 
5912329ecc3SAlex Crichton                 #[inline]
5927dba8efdSNick Fitzgerald                 fn linear_lift_from_memory(
5935a6ed0fbSAlex Crichton                     cx: &mut #internal::LiftContext<'_>,
594e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
595e8f4f862SAlex Crichton                     bytes: &[u8],
596*96e19700SNick Fitzgerald                 ) -> #wt::Result<Self> {
59744220746SAlex Crichton                     let align = <Self as #wt::component::ComponentType>::ALIGN32;
5982329ecc3SAlex Crichton                     debug_assert!((bytes.as_ptr() as usize) % (align as usize) == 0);
5992329ecc3SAlex Crichton                     let discrim = #from_bytes;
6002329ecc3SAlex Crichton                     let payload_offset = <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32;
6012329ecc3SAlex Crichton                     let payload = &bytes[payload_offset..];
602e8f4f862SAlex Crichton                     #extract_ty
6032329ecc3SAlex Crichton                     Ok(match discrim {
6042329ecc3SAlex Crichton                         #loads
605*96e19700SNick Fitzgerald                         discrim => #wt::bail!("unexpected discriminant: {}", discrim),
6062329ecc3SAlex Crichton                     })
6072329ecc3SAlex Crichton                 }
6082329ecc3SAlex Crichton             }
6092329ecc3SAlex Crichton         };
6102329ecc3SAlex Crichton 
6112329ecc3SAlex Crichton         Ok(expanded)
6122329ecc3SAlex Crichton     }
613fa41d131SAlex Crichton 
expand_enum( &self, name: &syn::Ident, discriminant_size: DiscriminantSize, cases: &[VariantCase], wt: &syn::Path, ) -> Result<TokenStream>614fa41d131SAlex Crichton     fn expand_enum(
615fa41d131SAlex Crichton         &self,
616fa41d131SAlex Crichton         name: &syn::Ident,
617fa41d131SAlex Crichton         discriminant_size: DiscriminantSize,
618fa41d131SAlex Crichton         cases: &[VariantCase],
619fa41d131SAlex Crichton         wt: &syn::Path,
620fa41d131SAlex Crichton     ) -> Result<TokenStream> {
621fa41d131SAlex Crichton         let internal = quote!(#wt::component::__internal);
622fa41d131SAlex Crichton 
623fa41d131SAlex Crichton         let (from_bytes, discrim_ty) = match discriminant_size {
624fa41d131SAlex Crichton             DiscriminantSize::Size1 => (quote!(bytes[0]), quote!(u8)),
625fa41d131SAlex Crichton             DiscriminantSize::Size2 => (
626fa41d131SAlex Crichton                 quote!(u16::from_le_bytes(bytes[0..2].try_into()?)),
627fa41d131SAlex Crichton                 quote!(u16),
628fa41d131SAlex Crichton             ),
629fa41d131SAlex Crichton             DiscriminantSize::Size4 => (
630fa41d131SAlex Crichton                 quote!(u32::from_le_bytes(bytes[0..4].try_into()?)),
631fa41d131SAlex Crichton                 quote!(u32),
632fa41d131SAlex Crichton             ),
633fa41d131SAlex Crichton         };
63485eed831SAlex Crichton         let discrim_limit = proc_macro2::Literal::u32_suffixed(cases.len().try_into().unwrap());
635fa41d131SAlex Crichton 
636fa41d131SAlex Crichton         let extract_ty = quote! {
637fa41d131SAlex Crichton             let ty = match ty {
638fa41d131SAlex Crichton                 #internal::InterfaceType::Enum(i) => &cx.types[i],
639fa41d131SAlex Crichton                 _ => #internal::bad_type_info(),
640fa41d131SAlex Crichton             };
641fa41d131SAlex Crichton         };
642fa41d131SAlex Crichton 
643fa41d131SAlex Crichton         let expanded = quote! {
644fa41d131SAlex Crichton             unsafe impl #wt::component::Lift for #name {
645fa41d131SAlex Crichton                 #[inline]
6467dba8efdSNick Fitzgerald                 fn linear_lift_from_flat(
647fa41d131SAlex Crichton                     cx: &mut #internal::LiftContext<'_>,
648fa41d131SAlex Crichton                     ty: #internal::InterfaceType,
649fa41d131SAlex Crichton                     src: &Self::Lower,
650*96e19700SNick Fitzgerald                 ) -> #wt::Result<Self> {
651fa41d131SAlex Crichton                     #extract_ty
652fa41d131SAlex Crichton                     let discrim = src.tag.get_u32();
653fa41d131SAlex Crichton                     if discrim >= #discrim_limit {
654*96e19700SNick Fitzgerald                         #wt::bail!("unexpected discriminant: {discrim}");
655fa41d131SAlex Crichton                     }
656fa41d131SAlex Crichton                     Ok(unsafe {
657fa41d131SAlex Crichton                         #internal::transmute::<#discrim_ty, #name>(discrim as #discrim_ty)
658fa41d131SAlex Crichton                     })
659fa41d131SAlex Crichton                 }
660fa41d131SAlex Crichton 
661fa41d131SAlex Crichton                 #[inline]
6627dba8efdSNick Fitzgerald                 fn linear_lift_from_memory(
663fa41d131SAlex Crichton                     cx: &mut #internal::LiftContext<'_>,
664fa41d131SAlex Crichton                     ty: #internal::InterfaceType,
665fa41d131SAlex Crichton                     bytes: &[u8],
666*96e19700SNick Fitzgerald                 ) -> #wt::Result<Self> {
667fa41d131SAlex Crichton                     let align = <Self as #wt::component::ComponentType>::ALIGN32;
668fa41d131SAlex Crichton                     debug_assert!((bytes.as_ptr() as usize) % (align as usize) == 0);
669fa41d131SAlex Crichton                     let discrim = #from_bytes;
67085eed831SAlex Crichton                     if u32::from(discrim) >= #discrim_limit {
671*96e19700SNick Fitzgerald                         #wt::bail!("unexpected discriminant: {discrim}");
672fa41d131SAlex Crichton                     }
673fa41d131SAlex Crichton                     Ok(unsafe {
674fa41d131SAlex Crichton                         #internal::transmute::<#discrim_ty, #name>(discrim)
675fa41d131SAlex Crichton                     })
676fa41d131SAlex Crichton                 }
677fa41d131SAlex Crichton             }
678fa41d131SAlex Crichton         };
679fa41d131SAlex Crichton 
680fa41d131SAlex Crichton         Ok(expanded)
681fa41d131SAlex Crichton     }
6822329ecc3SAlex Crichton }
6832329ecc3SAlex Crichton 
6842329ecc3SAlex Crichton pub struct LowerExpander;
6852329ecc3SAlex Crichton 
6862329ecc3SAlex Crichton impl Expander for LowerExpander {
expand_record( &self, name: &syn::Ident, generics: &syn::Generics, fields: &[&syn::Field], wt: &syn::Path, ) -> Result<TokenStream>6872329ecc3SAlex Crichton     fn expand_record(
6882329ecc3SAlex Crichton         &self,
6892329ecc3SAlex Crichton         name: &syn::Ident,
6902329ecc3SAlex Crichton         generics: &syn::Generics,
6912329ecc3SAlex Crichton         fields: &[&syn::Field],
69244220746SAlex Crichton         wt: &syn::Path,
6932329ecc3SAlex Crichton     ) -> Result<TokenStream> {
69444220746SAlex Crichton         let internal = quote!(#wt::component::__internal);
6952329ecc3SAlex Crichton 
6962329ecc3SAlex Crichton         let mut lowers = TokenStream::new();
6972329ecc3SAlex Crichton         let mut stores = TokenStream::new();
6982329ecc3SAlex Crichton 
699e8f4f862SAlex Crichton         for (i, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
700e8f4f862SAlex Crichton             let field_ty = quote!(ty.fields[#i].ty);
7017dba8efdSNick Fitzgerald             lowers.extend(quote!(#wt::component::Lower::linear_lower_to_flat(
702e8f4f862SAlex Crichton                 &self.#ident, cx, #field_ty, #internal::map_maybe_uninit!(dst.#ident)
7032329ecc3SAlex Crichton             )?;));
7042329ecc3SAlex Crichton 
7057dba8efdSNick Fitzgerald             stores.extend(quote!(#wt::component::Lower::linear_lower_to_memory(
7062329ecc3SAlex Crichton                 &self.#ident,
707e8f4f862SAlex Crichton                 cx,
708e8f4f862SAlex Crichton                 #field_ty,
70944220746SAlex Crichton                 <#ty as #wt::component::ComponentType>::ABI.next_field32_size(&mut offset),
7102329ecc3SAlex Crichton             )?;));
7112329ecc3SAlex Crichton         }
7122329ecc3SAlex Crichton 
71344220746SAlex Crichton         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lower));
7142329ecc3SAlex Crichton         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
7152329ecc3SAlex Crichton 
716e8f4f862SAlex Crichton         let extract_ty = quote! {
717e8f4f862SAlex Crichton             let ty = match ty {
718e8f4f862SAlex Crichton                 #internal::InterfaceType::Record(i) => &cx.types[i],
719e8f4f862SAlex Crichton                 _ => #internal::bad_type_info(),
720e8f4f862SAlex Crichton             };
721e8f4f862SAlex Crichton         };
722e8f4f862SAlex Crichton 
7232329ecc3SAlex Crichton         let expanded = quote! {
72444220746SAlex Crichton             unsafe impl #impl_generics #wt::component::Lower for #name #ty_generics #where_clause {
7252329ecc3SAlex Crichton                 #[inline]
7267dba8efdSNick Fitzgerald                 fn linear_lower_to_flat<T>(
7272329ecc3SAlex Crichton                     &self,
728e8f4f862SAlex Crichton                     cx: &mut #internal::LowerContext<'_, T>,
729e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
73081a89169SAlex Crichton                     dst: &mut core::mem::MaybeUninit<Self::Lower>,
731*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
732e8f4f862SAlex Crichton                     #extract_ty
7332329ecc3SAlex Crichton                     #lowers
7342329ecc3SAlex Crichton                     Ok(())
7352329ecc3SAlex Crichton                 }
7362329ecc3SAlex Crichton 
7372329ecc3SAlex Crichton                 #[inline]
7387dba8efdSNick Fitzgerald                 fn linear_lower_to_memory<T>(
7392329ecc3SAlex Crichton                     &self,
740e8f4f862SAlex Crichton                     cx: &mut #internal::LowerContext<'_, T>,
741e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
7422329ecc3SAlex Crichton                     mut offset: usize
743*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
74444220746SAlex Crichton                     debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
745e8f4f862SAlex Crichton                     #extract_ty
7462329ecc3SAlex Crichton                     #stores
7472329ecc3SAlex Crichton                     Ok(())
7482329ecc3SAlex Crichton                 }
7492329ecc3SAlex Crichton             }
7502329ecc3SAlex Crichton         };
7512329ecc3SAlex Crichton 
7522329ecc3SAlex Crichton         Ok(expanded)
7532329ecc3SAlex Crichton     }
7542329ecc3SAlex Crichton 
expand_variant( &self, name: &syn::Ident, generics: &syn::Generics, discriminant_size: DiscriminantSize, cases: &[VariantCase], wt: &syn::Path, ) -> Result<TokenStream>7552329ecc3SAlex Crichton     fn expand_variant(
7562329ecc3SAlex Crichton         &self,
7572329ecc3SAlex Crichton         name: &syn::Ident,
7582329ecc3SAlex Crichton         generics: &syn::Generics,
7592329ecc3SAlex Crichton         discriminant_size: DiscriminantSize,
7602329ecc3SAlex Crichton         cases: &[VariantCase],
76144220746SAlex Crichton         wt: &syn::Path,
7622329ecc3SAlex Crichton     ) -> Result<TokenStream> {
76344220746SAlex Crichton         let internal = quote!(#wt::component::__internal);
7642329ecc3SAlex Crichton 
7652329ecc3SAlex Crichton         let mut lowers = TokenStream::new();
7662329ecc3SAlex Crichton         let mut stores = TokenStream::new();
7672329ecc3SAlex Crichton 
7682329ecc3SAlex Crichton         for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() {
7692329ecc3SAlex Crichton             let index_u32 = u32::try_from(index).unwrap();
7702329ecc3SAlex Crichton 
7712329ecc3SAlex Crichton             let index_quoted = quote(discriminant_size, index);
7722329ecc3SAlex Crichton 
7732329ecc3SAlex Crichton             let discriminant_size = usize::from(discriminant_size);
7742329ecc3SAlex Crichton 
7752329ecc3SAlex Crichton             let pattern;
7762329ecc3SAlex Crichton             let lower;
7772329ecc3SAlex Crichton             let store;
7782329ecc3SAlex Crichton 
7792329ecc3SAlex Crichton             if ty.is_some() {
780fa41d131SAlex Crichton                 let ty = quote!(ty.cases[#index].unwrap_or_else(#internal::bad_type_info));
7812329ecc3SAlex Crichton                 pattern = quote!(Self::#ident(value));
7827dba8efdSNick Fitzgerald                 lower = quote!(value.linear_lower_to_flat(cx, #ty, dst));
7837dba8efdSNick Fitzgerald                 store = quote!(value.linear_lower_to_memory(
784e8f4f862SAlex Crichton                     cx,
785e8f4f862SAlex Crichton                     #ty,
7862329ecc3SAlex Crichton                     offset + <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32,
7872329ecc3SAlex Crichton                 ));
7882329ecc3SAlex Crichton             } else {
7892329ecc3SAlex Crichton                 pattern = quote!(Self::#ident);
7902329ecc3SAlex Crichton                 lower = quote!(Ok(()));
7912329ecc3SAlex Crichton                 store = quote!(Ok(()));
7922329ecc3SAlex Crichton             }
7932329ecc3SAlex Crichton 
7942329ecc3SAlex Crichton             lowers.extend(quote!(#pattern => {
79544220746SAlex Crichton                 #internal::map_maybe_uninit!(dst.tag).write(#wt::ValRaw::u32(#index_u32));
7962329ecc3SAlex Crichton                 unsafe {
7972329ecc3SAlex Crichton                     #internal::lower_payload(
7982329ecc3SAlex Crichton                         #internal::map_maybe_uninit!(dst.payload),
7992329ecc3SAlex Crichton                         |payload| #internal::map_maybe_uninit!(payload.#ident),
8002329ecc3SAlex Crichton                         |dst| #lower,
8012329ecc3SAlex Crichton                     )
8022329ecc3SAlex Crichton                 }
8032329ecc3SAlex Crichton             }));
8042329ecc3SAlex Crichton 
8052329ecc3SAlex Crichton             stores.extend(quote!(#pattern => {
806e8f4f862SAlex Crichton                 *cx.get::<#discriminant_size>(offset) = #index_quoted.to_le_bytes();
8072329ecc3SAlex Crichton                 #store
8082329ecc3SAlex Crichton             }));
8092329ecc3SAlex Crichton         }
8102329ecc3SAlex Crichton 
81144220746SAlex Crichton         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lower));
8122329ecc3SAlex Crichton         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
8132329ecc3SAlex Crichton 
814e8f4f862SAlex Crichton         let extract_ty = quote! {
815e8f4f862SAlex Crichton             let ty = match ty {
816fa41d131SAlex Crichton                 #internal::InterfaceType::Variant(i) => &cx.types[i],
817e8f4f862SAlex Crichton                 _ => #internal::bad_type_info(),
818e8f4f862SAlex Crichton             };
819e8f4f862SAlex Crichton         };
820e8f4f862SAlex Crichton 
8212329ecc3SAlex Crichton         let expanded = quote! {
82244220746SAlex Crichton             unsafe impl #impl_generics #wt::component::Lower for #name #ty_generics #where_clause {
8232329ecc3SAlex Crichton                 #[inline]
8247dba8efdSNick Fitzgerald                 fn linear_lower_to_flat<T>(
8252329ecc3SAlex Crichton                     &self,
826e8f4f862SAlex Crichton                     cx: &mut #internal::LowerContext<'_, T>,
827e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
82881a89169SAlex Crichton                     dst: &mut core::mem::MaybeUninit<Self::Lower>,
829*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
830e8f4f862SAlex Crichton                     #extract_ty
8312329ecc3SAlex Crichton                     match self {
8322329ecc3SAlex Crichton                         #lowers
8332329ecc3SAlex Crichton                     }
8342329ecc3SAlex Crichton                 }
8352329ecc3SAlex Crichton 
8362329ecc3SAlex Crichton                 #[inline]
8377dba8efdSNick Fitzgerald                 fn linear_lower_to_memory<T>(
8382329ecc3SAlex Crichton                     &self,
839e8f4f862SAlex Crichton                     cx: &mut #internal::LowerContext<'_, T>,
840e8f4f862SAlex Crichton                     ty: #internal::InterfaceType,
8412329ecc3SAlex Crichton                     mut offset: usize
842*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
843e8f4f862SAlex Crichton                     #extract_ty
84444220746SAlex Crichton                     debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
8452329ecc3SAlex Crichton                     match self {
8462329ecc3SAlex Crichton                         #stores
8472329ecc3SAlex Crichton                     }
8482329ecc3SAlex Crichton                 }
8492329ecc3SAlex Crichton             }
8502329ecc3SAlex Crichton         };
8512329ecc3SAlex Crichton 
8522329ecc3SAlex Crichton         Ok(expanded)
8532329ecc3SAlex Crichton     }
854fa41d131SAlex Crichton 
expand_enum( &self, name: &syn::Ident, discriminant_size: DiscriminantSize, _cases: &[VariantCase], wt: &syn::Path, ) -> Result<TokenStream>855fa41d131SAlex Crichton     fn expand_enum(
856fa41d131SAlex Crichton         &self,
857fa41d131SAlex Crichton         name: &syn::Ident,
858fa41d131SAlex Crichton         discriminant_size: DiscriminantSize,
859fa41d131SAlex Crichton         _cases: &[VariantCase],
860fa41d131SAlex Crichton         wt: &syn::Path,
861fa41d131SAlex Crichton     ) -> Result<TokenStream> {
862fa41d131SAlex Crichton         let internal = quote!(#wt::component::__internal);
863fa41d131SAlex Crichton 
864fa41d131SAlex Crichton         let extract_ty = quote! {
865fa41d131SAlex Crichton             let ty = match ty {
866fa41d131SAlex Crichton                 #internal::InterfaceType::Enum(i) => &cx.types[i],
867fa41d131SAlex Crichton                 _ => #internal::bad_type_info(),
868fa41d131SAlex Crichton             };
869fa41d131SAlex Crichton         };
870fa41d131SAlex Crichton 
871fa41d131SAlex Crichton         let (size, ty) = match discriminant_size {
872fa41d131SAlex Crichton             DiscriminantSize::Size1 => (1, quote!(u8)),
873fa41d131SAlex Crichton             DiscriminantSize::Size2 => (2, quote!(u16)),
874fa41d131SAlex Crichton             DiscriminantSize::Size4 => (4, quote!(u32)),
875fa41d131SAlex Crichton         };
876fa41d131SAlex Crichton         let size = proc_macro2::Literal::usize_unsuffixed(size);
877fa41d131SAlex Crichton 
878fa41d131SAlex Crichton         let expanded = quote! {
879fa41d131SAlex Crichton             unsafe impl #wt::component::Lower for #name {
880fa41d131SAlex Crichton                 #[inline]
8817dba8efdSNick Fitzgerald                 fn linear_lower_to_flat<T>(
882fa41d131SAlex Crichton                     &self,
883fa41d131SAlex Crichton                     cx: &mut #internal::LowerContext<'_, T>,
884fa41d131SAlex Crichton                     ty: #internal::InterfaceType,
885fa41d131SAlex Crichton                     dst: &mut core::mem::MaybeUninit<Self::Lower>,
886*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
887fa41d131SAlex Crichton                     #extract_ty
888fa41d131SAlex Crichton                     #internal::map_maybe_uninit!(dst.tag)
889fa41d131SAlex Crichton                         .write(#wt::ValRaw::u32(*self as u32));
890fa41d131SAlex Crichton                     Ok(())
891fa41d131SAlex Crichton                 }
892fa41d131SAlex Crichton 
893fa41d131SAlex Crichton                 #[inline]
8947dba8efdSNick Fitzgerald                 fn linear_lower_to_memory<T>(
895fa41d131SAlex Crichton                     &self,
896fa41d131SAlex Crichton                     cx: &mut #internal::LowerContext<'_, T>,
897fa41d131SAlex Crichton                     ty: #internal::InterfaceType,
898fa41d131SAlex Crichton                     mut offset: usize
899*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
900fa41d131SAlex Crichton                     #extract_ty
901fa41d131SAlex Crichton                     debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
902fa41d131SAlex Crichton                     let discrim = *self as #ty;
903fa41d131SAlex Crichton                     *cx.get::<#size>(offset) = discrim.to_le_bytes();
904fa41d131SAlex Crichton                     Ok(())
905fa41d131SAlex Crichton                 }
906fa41d131SAlex Crichton             }
907fa41d131SAlex Crichton         };
908fa41d131SAlex Crichton 
909fa41d131SAlex Crichton         Ok(expanded)
910fa41d131SAlex Crichton     }
9112329ecc3SAlex Crichton }
9122329ecc3SAlex Crichton 
9132329ecc3SAlex Crichton pub struct ComponentTypeExpander;
9142329ecc3SAlex Crichton 
9152329ecc3SAlex Crichton impl Expander for ComponentTypeExpander {
expand_record( &self, name: &syn::Ident, generics: &syn::Generics, fields: &[&syn::Field], wt: &syn::Path, ) -> Result<TokenStream>9162329ecc3SAlex Crichton     fn expand_record(
9172329ecc3SAlex Crichton         &self,
9182329ecc3SAlex Crichton         name: &syn::Ident,
9192329ecc3SAlex Crichton         generics: &syn::Generics,
9202329ecc3SAlex Crichton         fields: &[&syn::Field],
92144220746SAlex Crichton         wt: &syn::Path,
9222329ecc3SAlex Crichton     ) -> Result<TokenStream> {
9232329ecc3SAlex Crichton         expand_record_for_component_type(
9242329ecc3SAlex Crichton             name,
9252329ecc3SAlex Crichton             generics,
9262329ecc3SAlex Crichton             fields,
9272329ecc3SAlex Crichton             quote!(typecheck_record),
9282329ecc3SAlex Crichton             fields
9292329ecc3SAlex Crichton                 .iter()
9302329ecc3SAlex Crichton                 .map(
9312329ecc3SAlex Crichton                     |syn::Field {
9322329ecc3SAlex Crichton                          attrs, ident, ty, ..
9332329ecc3SAlex Crichton                      }| {
9342329ecc3SAlex Crichton                         let name = find_rename(attrs)?.unwrap_or_else(|| {
9356d7bb360SAlex Crichton                             let ident = ident.as_ref().unwrap();
9366d7bb360SAlex Crichton                             syn::LitStr::new(&ident.to_string(), ident.span())
9372329ecc3SAlex Crichton                         });
9382329ecc3SAlex Crichton 
93944220746SAlex Crichton                         Ok(quote!((#name, <#ty as #wt::component::ComponentType>::typecheck),))
9402329ecc3SAlex Crichton                     },
9412329ecc3SAlex Crichton                 )
9422329ecc3SAlex Crichton                 .collect::<Result<_>>()?,
94344220746SAlex Crichton             wt,
9442329ecc3SAlex Crichton         )
9452329ecc3SAlex Crichton     }
9462329ecc3SAlex Crichton 
expand_variant( &self, name: &syn::Ident, generics: &syn::Generics, _discriminant_size: DiscriminantSize, cases: &[VariantCase], wt: &syn::Path, ) -> Result<TokenStream>9472329ecc3SAlex Crichton     fn expand_variant(
9482329ecc3SAlex Crichton         &self,
9492329ecc3SAlex Crichton         name: &syn::Ident,
9502329ecc3SAlex Crichton         generics: &syn::Generics,
9512329ecc3SAlex Crichton         _discriminant_size: DiscriminantSize,
9522329ecc3SAlex Crichton         cases: &[VariantCase],
95344220746SAlex Crichton         wt: &syn::Path,
9542329ecc3SAlex Crichton     ) -> Result<TokenStream> {
95544220746SAlex Crichton         let internal = quote!(#wt::component::__internal);
9562329ecc3SAlex Crichton 
9572329ecc3SAlex Crichton         let mut case_names_and_checks = TokenStream::new();
9582329ecc3SAlex Crichton         let mut lower_payload_generic_params = TokenStream::new();
9592329ecc3SAlex Crichton         let mut lower_payload_generic_args = TokenStream::new();
9602329ecc3SAlex Crichton         let mut lower_payload_case_declarations = TokenStream::new();
9612329ecc3SAlex Crichton         let mut lower_generic_args = TokenStream::new();
9622329ecc3SAlex Crichton         let mut abi_list = TokenStream::new();
9632329ecc3SAlex Crichton         let mut unique_types = HashSet::new();
9642329ecc3SAlex Crichton 
9652329ecc3SAlex Crichton         for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() {
9662329ecc3SAlex Crichton             let rename = find_rename(attrs)?;
9672329ecc3SAlex Crichton 
9686d7bb360SAlex Crichton             let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span()));
9692329ecc3SAlex Crichton 
9702329ecc3SAlex Crichton             if let Some(ty) = ty {
97144220746SAlex Crichton                 abi_list.extend(quote!(Some(<#ty as #wt::component::ComponentType>::ABI),));
9722329ecc3SAlex Crichton 
973fa41d131SAlex Crichton                 case_names_and_checks.extend(
974fa41d131SAlex Crichton                     quote!((#name, Some(<#ty as #wt::component::ComponentType>::typecheck)),),
975fa41d131SAlex Crichton                 );
9762329ecc3SAlex Crichton 
9772329ecc3SAlex Crichton                 let generic = format_ident!("T{}", index);
9782329ecc3SAlex Crichton 
9792329ecc3SAlex Crichton                 lower_payload_generic_params.extend(quote!(#generic: Copy,));
9802329ecc3SAlex Crichton                 lower_payload_generic_args.extend(quote!(#generic,));
9812329ecc3SAlex Crichton                 lower_payload_case_declarations.extend(quote!(#ident: #generic,));
98244220746SAlex Crichton                 lower_generic_args.extend(quote!(<#ty as #wt::component::ComponentType>::Lower,));
9832329ecc3SAlex Crichton 
9842329ecc3SAlex Crichton                 unique_types.insert(ty);
9852329ecc3SAlex Crichton             } else {
9862329ecc3SAlex Crichton                 abi_list.extend(quote!(None,));
987fa41d131SAlex Crichton                 case_names_and_checks.extend(quote!((#name, None),));
98844220746SAlex Crichton                 lower_payload_case_declarations.extend(quote!(#ident: [#wt::ValRaw; 0],));
9892329ecc3SAlex Crichton             }
9902329ecc3SAlex Crichton         }
9912329ecc3SAlex Crichton 
99244220746SAlex Crichton         let generics = add_trait_bounds(generics, parse_quote!(#wt::component::ComponentType));
9932329ecc3SAlex Crichton         let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
9942329ecc3SAlex Crichton         let lower = format_ident!("Lower{}", name);
9952329ecc3SAlex Crichton         let lower_payload = format_ident!("LowerPayload{}", name);
9962329ecc3SAlex Crichton 
9972329ecc3SAlex Crichton         // You may wonder why we make the types of all the fields of the #lower struct and #lower_payload union
9982329ecc3SAlex Crichton         // generic.  This is to work around a [normalization bug in
9992329ecc3SAlex Crichton         // rustc](https://github.com/rust-lang/rust/issues/90903) such that the compiler does not understand that
10002329ecc3SAlex Crichton         // e.g. `<i32 as ComponentType>::Lower` is `Copy` despite the bound specified in `ComponentType`'s
10012329ecc3SAlex Crichton         // definition.
10022329ecc3SAlex Crichton         //
10032329ecc3SAlex Crichton         // See also the comment in `Self::expand_record` above for another reason why we do this.
10042329ecc3SAlex Crichton 
10052329ecc3SAlex Crichton         let expanded = quote! {
10062329ecc3SAlex Crichton             #[doc(hidden)]
10072329ecc3SAlex Crichton             #[derive(Clone, Copy)]
10082329ecc3SAlex Crichton             #[repr(C)]
10092329ecc3SAlex Crichton             pub struct #lower<#lower_payload_generic_params> {
101044220746SAlex Crichton                 tag: #wt::ValRaw,
10112329ecc3SAlex Crichton                 payload: #lower_payload<#lower_payload_generic_args>
10122329ecc3SAlex Crichton             }
10132329ecc3SAlex Crichton 
10142329ecc3SAlex Crichton             #[doc(hidden)]
10152329ecc3SAlex Crichton             #[allow(non_snake_case)]
10162329ecc3SAlex Crichton             #[derive(Clone, Copy)]
10172329ecc3SAlex Crichton             #[repr(C)]
10182329ecc3SAlex Crichton             union #lower_payload<#lower_payload_generic_params> {
10192329ecc3SAlex Crichton                 #lower_payload_case_declarations
10202329ecc3SAlex Crichton             }
10212329ecc3SAlex Crichton 
102244220746SAlex Crichton             unsafe impl #impl_generics #wt::component::ComponentType for #name #ty_generics #where_clause {
10232329ecc3SAlex Crichton                 type Lower = #lower<#lower_generic_args>;
10242329ecc3SAlex Crichton 
10252329ecc3SAlex Crichton                 #[inline]
10262329ecc3SAlex Crichton                 fn typecheck(
10272329ecc3SAlex Crichton                     ty: &#internal::InterfaceType,
10285a6ed0fbSAlex Crichton                     types: &#internal::InstanceType<'_>,
1029*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
1030fa41d131SAlex Crichton                     #internal::typecheck_variant(ty, types, &[#case_names_and_checks])
10312329ecc3SAlex Crichton                 }
10322329ecc3SAlex Crichton 
10332329ecc3SAlex Crichton                 const ABI: #internal::CanonicalAbiInfo =
10342329ecc3SAlex Crichton                     #internal::CanonicalAbiInfo::variant_static(&[#abi_list]);
10352329ecc3SAlex Crichton             }
10362329ecc3SAlex Crichton 
10372329ecc3SAlex Crichton             unsafe impl #impl_generics #internal::ComponentVariant for #name #ty_generics #where_clause {
10382329ecc3SAlex Crichton                 const CASES: &'static [Option<#internal::CanonicalAbiInfo>] = &[#abi_list];
10392329ecc3SAlex Crichton             }
10402329ecc3SAlex Crichton         };
10412329ecc3SAlex Crichton 
10422329ecc3SAlex Crichton         Ok(quote!(const _: () = { #expanded };))
10432329ecc3SAlex Crichton     }
1044fa41d131SAlex Crichton 
expand_enum( &self, name: &syn::Ident, _discriminant_size: DiscriminantSize, cases: &[VariantCase], wt: &syn::Path, ) -> Result<TokenStream>1045fa41d131SAlex Crichton     fn expand_enum(
1046fa41d131SAlex Crichton         &self,
1047fa41d131SAlex Crichton         name: &syn::Ident,
1048fa41d131SAlex Crichton         _discriminant_size: DiscriminantSize,
1049fa41d131SAlex Crichton         cases: &[VariantCase],
1050fa41d131SAlex Crichton         wt: &syn::Path,
1051fa41d131SAlex Crichton     ) -> Result<TokenStream> {
1052fa41d131SAlex Crichton         let internal = quote!(#wt::component::__internal);
1053fa41d131SAlex Crichton 
1054fa41d131SAlex Crichton         let mut case_names = TokenStream::new();
1055fa41d131SAlex Crichton         let mut abi_list = TokenStream::new();
1056fa41d131SAlex Crichton 
1057fa41d131SAlex Crichton         for VariantCase { attrs, ident, ty } in cases.iter() {
1058fa41d131SAlex Crichton             let rename = find_rename(attrs)?;
1059fa41d131SAlex Crichton 
1060fa41d131SAlex Crichton             let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span()));
1061fa41d131SAlex Crichton 
1062fa41d131SAlex Crichton             if ty.is_some() {
1063fa41d131SAlex Crichton                 return Err(Error::new(
1064fa41d131SAlex Crichton                     ident.span(),
1065fa41d131SAlex Crichton                     "payloads are not permitted for `enum` cases",
1066fa41d131SAlex Crichton                 ));
1067fa41d131SAlex Crichton             }
1068fa41d131SAlex Crichton             abi_list.extend(quote!(None,));
1069fa41d131SAlex Crichton             case_names.extend(quote!(#name,));
1070fa41d131SAlex Crichton         }
1071fa41d131SAlex Crichton 
1072fa41d131SAlex Crichton         let lower = format_ident!("Lower{}", name);
1073fa41d131SAlex Crichton 
1074fa41d131SAlex Crichton         let cases_len = cases.len();
1075fa41d131SAlex Crichton         let expanded = quote! {
1076fa41d131SAlex Crichton             #[doc(hidden)]
1077fa41d131SAlex Crichton             #[derive(Clone, Copy)]
1078fa41d131SAlex Crichton             #[repr(C)]
1079fa41d131SAlex Crichton             pub struct #lower {
1080fa41d131SAlex Crichton                 tag: #wt::ValRaw,
1081fa41d131SAlex Crichton             }
1082fa41d131SAlex Crichton 
1083fa41d131SAlex Crichton             unsafe impl #wt::component::ComponentType for #name {
1084fa41d131SAlex Crichton                 type Lower = #lower;
1085fa41d131SAlex Crichton 
1086fa41d131SAlex Crichton                 #[inline]
1087fa41d131SAlex Crichton                 fn typecheck(
1088fa41d131SAlex Crichton                     ty: &#internal::InterfaceType,
1089fa41d131SAlex Crichton                     types: &#internal::InstanceType<'_>,
1090*96e19700SNick Fitzgerald                 ) -> #wt::Result<()> {
1091fa41d131SAlex Crichton                     #internal::typecheck_enum(ty, types, &[#case_names])
1092fa41d131SAlex Crichton                 }
1093fa41d131SAlex Crichton 
1094fa41d131SAlex Crichton                 const ABI: #internal::CanonicalAbiInfo =
1095fa41d131SAlex Crichton                     #internal::CanonicalAbiInfo::enum_(#cases_len);
1096fa41d131SAlex Crichton             }
1097fa41d131SAlex Crichton 
1098fa41d131SAlex Crichton             unsafe impl #internal::ComponentVariant for #name {
1099fa41d131SAlex Crichton                 const CASES: &'static [Option<#internal::CanonicalAbiInfo>] = &[#abi_list];
1100fa41d131SAlex Crichton             }
1101fa41d131SAlex Crichton         };
1102fa41d131SAlex Crichton 
1103fa41d131SAlex Crichton         Ok(quote!(const _: () = { #expanded };))
1104fa41d131SAlex Crichton     }
11052329ecc3SAlex Crichton }
11062329ecc3SAlex Crichton 
11072329ecc3SAlex Crichton #[derive(Debug)]
11082329ecc3SAlex Crichton struct Flag {
11092329ecc3SAlex Crichton     rename: Option<String>,
11102329ecc3SAlex Crichton     name: String,
11112329ecc3SAlex Crichton }
11122329ecc3SAlex Crichton 
11132329ecc3SAlex Crichton impl Parse for Flag {
parse(input: ParseStream) -> Result<Self>11142329ecc3SAlex Crichton     fn parse(input: ParseStream) -> Result<Self> {
11152329ecc3SAlex Crichton         let attributes = syn::Attribute::parse_outer(input)?;
11162329ecc3SAlex Crichton 
11176d7bb360SAlex Crichton         let rename = find_rename(&attributes)?.map(|literal| literal.value());
11182329ecc3SAlex Crichton 
11192329ecc3SAlex Crichton         input.parse::<Token![const]>()?;
11202329ecc3SAlex Crichton         let name = input.parse::<syn::Ident>()?.to_string();
11212329ecc3SAlex Crichton 
11222329ecc3SAlex Crichton         Ok(Self { rename, name })
11232329ecc3SAlex Crichton     }
11242329ecc3SAlex Crichton }
11252329ecc3SAlex Crichton 
11262329ecc3SAlex Crichton #[derive(Debug)]
11272329ecc3SAlex Crichton pub struct Flags {
11282329ecc3SAlex Crichton     name: String,
11292329ecc3SAlex Crichton     flags: Vec<Flag>,
11302329ecc3SAlex Crichton }
11312329ecc3SAlex Crichton 
11322329ecc3SAlex Crichton impl Parse for Flags {
parse(input: ParseStream) -> Result<Self>11332329ecc3SAlex Crichton     fn parse(input: ParseStream) -> Result<Self> {
11342329ecc3SAlex Crichton         let name = input.parse::<syn::Ident>()?.to_string();
11352329ecc3SAlex Crichton 
11362329ecc3SAlex Crichton         let content;
11372329ecc3SAlex Crichton         braced!(content in input);
11382329ecc3SAlex Crichton 
11392329ecc3SAlex Crichton         let flags = content
11406d7bb360SAlex Crichton             .parse_terminated(Flag::parse, Token![;])?
11412329ecc3SAlex Crichton             .into_iter()
11422329ecc3SAlex Crichton             .collect();
11432329ecc3SAlex Crichton 
11442329ecc3SAlex Crichton         Ok(Self { name, flags })
11452329ecc3SAlex Crichton     }
11462329ecc3SAlex Crichton }
11472329ecc3SAlex Crichton 
expand_flags(flags: &Flags) -> Result<TokenStream>11482329ecc3SAlex Crichton pub fn expand_flags(flags: &Flags) -> Result<TokenStream> {
114944220746SAlex Crichton     let wt = default_wasmtime_crate();
11502329ecc3SAlex Crichton     let size = FlagsSize::from_count(flags.flags.len());
11512329ecc3SAlex Crichton 
11522329ecc3SAlex Crichton     let ty;
11532329ecc3SAlex Crichton     let eq;
11542329ecc3SAlex Crichton 
11552329ecc3SAlex Crichton     let count = flags.flags.len();
11562329ecc3SAlex Crichton 
11572329ecc3SAlex Crichton     match size {
11582329ecc3SAlex Crichton         FlagsSize::Size0 => {
11592329ecc3SAlex Crichton             ty = quote!(());
11602329ecc3SAlex Crichton             eq = quote!(true);
11612329ecc3SAlex Crichton         }
11622329ecc3SAlex Crichton         FlagsSize::Size1 => {
11632329ecc3SAlex Crichton             ty = quote!(u8);
11642329ecc3SAlex Crichton 
11652329ecc3SAlex Crichton             eq = if count == 8 {
11662329ecc3SAlex Crichton                 quote!(self.__inner0.eq(&rhs.__inner0))
11672329ecc3SAlex Crichton             } else {
11682329ecc3SAlex Crichton                 let mask = !(0xFF_u8 << count);
11692329ecc3SAlex Crichton 
11702329ecc3SAlex Crichton                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
11712329ecc3SAlex Crichton             };
11722329ecc3SAlex Crichton         }
11732329ecc3SAlex Crichton         FlagsSize::Size2 => {
11742329ecc3SAlex Crichton             ty = quote!(u16);
11752329ecc3SAlex Crichton 
11762329ecc3SAlex Crichton             eq = if count == 16 {
11772329ecc3SAlex Crichton                 quote!(self.__inner0.eq(&rhs.__inner0))
11782329ecc3SAlex Crichton             } else {
11792329ecc3SAlex Crichton                 let mask = !(0xFFFF_u16 << count);
11802329ecc3SAlex Crichton 
11812329ecc3SAlex Crichton                 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask)))
11822329ecc3SAlex Crichton             };
11832329ecc3SAlex Crichton         }
11842329ecc3SAlex Crichton         FlagsSize::Size4Plus(n) => {
11852329ecc3SAlex Crichton             ty = quote!(u32);
11862329ecc3SAlex Crichton 
11872329ecc3SAlex Crichton             let comparisons = (0..(n - 1))
11882329ecc3SAlex Crichton                 .map(|index| {
11892329ecc3SAlex Crichton                     let field = format_ident!("__inner{}", index);
11902329ecc3SAlex Crichton 
11912329ecc3SAlex Crichton                     quote!(self.#field.eq(&rhs.#field) &&)
11922329ecc3SAlex Crichton                 })
11932329ecc3SAlex Crichton                 .collect::<TokenStream>();
11942329ecc3SAlex Crichton 
11952329ecc3SAlex Crichton             let field = format_ident!("__inner{}", n - 1);
11962329ecc3SAlex Crichton 
11972329ecc3SAlex Crichton             eq = if count % 32 == 0 {
11982329ecc3SAlex Crichton                 quote!(#comparisons self.#field.eq(&rhs.#field))
11992329ecc3SAlex Crichton             } else {
12002329ecc3SAlex Crichton                 let mask = !(0xFFFF_FFFF_u32 << (count % 32));
12012329ecc3SAlex Crichton 
12022329ecc3SAlex Crichton                 quote!(#comparisons (self.#field & #mask).eq(&(rhs.#field & #mask)))
12032329ecc3SAlex Crichton             }
12042329ecc3SAlex Crichton         }
12052329ecc3SAlex Crichton     }
12062329ecc3SAlex Crichton 
12072329ecc3SAlex Crichton     let count;
12082329ecc3SAlex Crichton     let mut as_array;
12092329ecc3SAlex Crichton     let mut bitor;
12102329ecc3SAlex Crichton     let mut bitor_assign;
12112329ecc3SAlex Crichton     let mut bitand;
12122329ecc3SAlex Crichton     let mut bitand_assign;
12132329ecc3SAlex Crichton     let mut bitxor;
12142329ecc3SAlex Crichton     let mut bitxor_assign;
12152329ecc3SAlex Crichton     let mut not;
12162329ecc3SAlex Crichton 
12172329ecc3SAlex Crichton     match size {
12182329ecc3SAlex Crichton         FlagsSize::Size0 => {
12192329ecc3SAlex Crichton             count = 0;
12202329ecc3SAlex Crichton             as_array = quote!([]);
12212329ecc3SAlex Crichton             bitor = quote!(Self {});
12222329ecc3SAlex Crichton             bitor_assign = quote!();
12232329ecc3SAlex Crichton             bitand = quote!(Self {});
12242329ecc3SAlex Crichton             bitand_assign = quote!();
12252329ecc3SAlex Crichton             bitxor = quote!(Self {});
12262329ecc3SAlex Crichton             bitxor_assign = quote!();
12272329ecc3SAlex Crichton             not = quote!(Self {});
12282329ecc3SAlex Crichton         }
12292329ecc3SAlex Crichton         FlagsSize::Size1 | FlagsSize::Size2 => {
12302329ecc3SAlex Crichton             count = 1;
12312329ecc3SAlex Crichton             as_array = quote!([self.__inner0 as u32]);
12322329ecc3SAlex Crichton             bitor = quote!(Self {
12332329ecc3SAlex Crichton                 __inner0: self.__inner0.bitor(rhs.__inner0)
12342329ecc3SAlex Crichton             });
12352329ecc3SAlex Crichton             bitor_assign = quote!(self.__inner0.bitor_assign(rhs.__inner0));
12362329ecc3SAlex Crichton             bitand = quote!(Self {
12372329ecc3SAlex Crichton                 __inner0: self.__inner0.bitand(rhs.__inner0)
12382329ecc3SAlex Crichton             });
12392329ecc3SAlex Crichton             bitand_assign = quote!(self.__inner0.bitand_assign(rhs.__inner0));
12402329ecc3SAlex Crichton             bitxor = quote!(Self {
12412329ecc3SAlex Crichton                 __inner0: self.__inner0.bitxor(rhs.__inner0)
12422329ecc3SAlex Crichton             });
12432329ecc3SAlex Crichton             bitxor_assign = quote!(self.__inner0.bitxor_assign(rhs.__inner0));
12442329ecc3SAlex Crichton             not = quote!(Self {
12452329ecc3SAlex Crichton                 __inner0: self.__inner0.not()
12462329ecc3SAlex Crichton             });
12472329ecc3SAlex Crichton         }
12482329ecc3SAlex Crichton         FlagsSize::Size4Plus(n) => {
12492329ecc3SAlex Crichton             count = usize::from(n);
12502329ecc3SAlex Crichton             as_array = TokenStream::new();
12512329ecc3SAlex Crichton             bitor = TokenStream::new();
12522329ecc3SAlex Crichton             bitor_assign = TokenStream::new();
12532329ecc3SAlex Crichton             bitand = TokenStream::new();
12542329ecc3SAlex Crichton             bitand_assign = TokenStream::new();
12552329ecc3SAlex Crichton             bitxor = TokenStream::new();
12562329ecc3SAlex Crichton             bitxor_assign = TokenStream::new();
12572329ecc3SAlex Crichton             not = TokenStream::new();
12582329ecc3SAlex Crichton 
12592329ecc3SAlex Crichton             for index in 0..n {
12602329ecc3SAlex Crichton                 let field = format_ident!("__inner{}", index);
12612329ecc3SAlex Crichton 
12622329ecc3SAlex Crichton                 as_array.extend(quote!(self.#field,));
12632329ecc3SAlex Crichton                 bitor.extend(quote!(#field: self.#field.bitor(rhs.#field),));
12642329ecc3SAlex Crichton                 bitor_assign.extend(quote!(self.#field.bitor_assign(rhs.#field);));
12652329ecc3SAlex Crichton                 bitand.extend(quote!(#field: self.#field.bitand(rhs.#field),));
12662329ecc3SAlex Crichton                 bitand_assign.extend(quote!(self.#field.bitand_assign(rhs.#field);));
12672329ecc3SAlex Crichton                 bitxor.extend(quote!(#field: self.#field.bitxor(rhs.#field),));
12682329ecc3SAlex Crichton                 bitxor_assign.extend(quote!(self.#field.bitxor_assign(rhs.#field);));
12692329ecc3SAlex Crichton                 not.extend(quote!(#field: self.#field.not(),));
12702329ecc3SAlex Crichton             }
12712329ecc3SAlex Crichton 
12722329ecc3SAlex Crichton             as_array = quote!([#as_array]);
12732329ecc3SAlex Crichton             bitor = quote!(Self { #bitor });
12742329ecc3SAlex Crichton             bitand = quote!(Self { #bitand });
12752329ecc3SAlex Crichton             bitxor = quote!(Self { #bitxor });
12762329ecc3SAlex Crichton             not = quote!(Self { #not });
12772329ecc3SAlex Crichton         }
12782329ecc3SAlex Crichton     };
12792329ecc3SAlex Crichton 
12802329ecc3SAlex Crichton     let name = format_ident!("{}", flags.name);
12812329ecc3SAlex Crichton 
12822329ecc3SAlex Crichton     let mut constants = TokenStream::new();
12832329ecc3SAlex Crichton     let mut rust_names = TokenStream::new();
12842329ecc3SAlex Crichton     let mut component_names = TokenStream::new();
12852329ecc3SAlex Crichton 
12862329ecc3SAlex Crichton     for (index, Flag { name, rename }) in flags.flags.iter().enumerate() {
12872329ecc3SAlex Crichton         rust_names.extend(quote!(#name,));
12882329ecc3SAlex Crichton 
12892329ecc3SAlex Crichton         let component_name = rename.as_ref().unwrap_or(name);
12902329ecc3SAlex Crichton         component_names.extend(quote!(#component_name,));
12912329ecc3SAlex Crichton 
12922329ecc3SAlex Crichton         let fields = match size {
12932329ecc3SAlex Crichton             FlagsSize::Size0 => quote!(),
12942329ecc3SAlex Crichton             FlagsSize::Size1 => {
12952329ecc3SAlex Crichton                 let init = 1_u8 << index;
12962329ecc3SAlex Crichton                 quote!(__inner0: #init)
12972329ecc3SAlex Crichton             }
12982329ecc3SAlex Crichton             FlagsSize::Size2 => {
12992329ecc3SAlex Crichton                 let init = 1_u16 << index;
13002329ecc3SAlex Crichton                 quote!(__inner0: #init)
13012329ecc3SAlex Crichton             }
13022329ecc3SAlex Crichton             FlagsSize::Size4Plus(n) => (0..n)
13032329ecc3SAlex Crichton                 .map(|i| {
13042329ecc3SAlex Crichton                     let field = format_ident!("__inner{}", i);
13052329ecc3SAlex Crichton 
13062329ecc3SAlex Crichton                     let init = if index / 32 == usize::from(i) {
13072329ecc3SAlex Crichton                         1_u32 << (index % 32)
13082329ecc3SAlex Crichton                     } else {
13092329ecc3SAlex Crichton                         0
13102329ecc3SAlex Crichton                     };
13112329ecc3SAlex Crichton 
13122329ecc3SAlex Crichton                     quote!(#field: #init,)
13132329ecc3SAlex Crichton                 })
13142329ecc3SAlex Crichton                 .collect::<TokenStream>(),
13152329ecc3SAlex Crichton         };
13162329ecc3SAlex Crichton 
13172329ecc3SAlex Crichton         let name = format_ident!("{}", name);
13182329ecc3SAlex Crichton 
13192329ecc3SAlex Crichton         constants.extend(quote!(pub const #name: Self = Self { #fields };));
13202329ecc3SAlex Crichton     }
13212329ecc3SAlex Crichton 
13222329ecc3SAlex Crichton     let generics = syn::Generics {
13232329ecc3SAlex Crichton         lt_token: None,
13242329ecc3SAlex Crichton         params: Punctuated::new(),
13252329ecc3SAlex Crichton         gt_token: None,
13262329ecc3SAlex Crichton         where_clause: None,
13272329ecc3SAlex Crichton     };
13282329ecc3SAlex Crichton 
13292329ecc3SAlex Crichton     let fields = {
13302329ecc3SAlex Crichton         let ty = syn::parse2::<syn::Type>(ty.clone())?;
13312329ecc3SAlex Crichton 
13322329ecc3SAlex Crichton         (0..count)
13332329ecc3SAlex Crichton             .map(|index| syn::Field {
13342329ecc3SAlex Crichton                 attrs: Vec::new(),
13352329ecc3SAlex Crichton                 vis: syn::Visibility::Inherited,
13362329ecc3SAlex Crichton                 ident: Some(format_ident!("__inner{}", index)),
13372329ecc3SAlex Crichton                 colon_token: None,
13382329ecc3SAlex Crichton                 ty: ty.clone(),
13396d7bb360SAlex Crichton                 mutability: syn::FieldMutability::None,
13402329ecc3SAlex Crichton             })
13412329ecc3SAlex Crichton             .collect::<Vec<_>>()
13422329ecc3SAlex Crichton     };
13432329ecc3SAlex Crichton 
13442329ecc3SAlex Crichton     let fields = fields.iter().collect::<Vec<_>>();
13452329ecc3SAlex Crichton 
13462329ecc3SAlex Crichton     let component_type_impl = expand_record_for_component_type(
13472329ecc3SAlex Crichton         &name,
13482329ecc3SAlex Crichton         &generics,
13492329ecc3SAlex Crichton         &fields,
13502329ecc3SAlex Crichton         quote!(typecheck_flags),
13512329ecc3SAlex Crichton         component_names,
135244220746SAlex Crichton         &wt,
13532329ecc3SAlex Crichton     )?;
13542329ecc3SAlex Crichton 
135544220746SAlex Crichton     let internal = quote!(#wt::component::__internal);
13562329ecc3SAlex Crichton 
1357e8f4f862SAlex Crichton     let field_names = fields
1358e8f4f862SAlex Crichton         .iter()
1359e8f4f862SAlex Crichton         .map(|syn::Field { ident, .. }| ident)
1360e8f4f862SAlex Crichton         .collect::<Vec<_>>();
1361e8f4f862SAlex Crichton 
13622329ecc3SAlex Crichton     let fields = fields
13632329ecc3SAlex Crichton         .iter()
13642329ecc3SAlex Crichton         .map(|syn::Field { ident, .. }| quote!(#[doc(hidden)] #ident: #ty,))
13652329ecc3SAlex Crichton         .collect::<TokenStream>();
13662329ecc3SAlex Crichton 
1367e8f4f862SAlex Crichton     let (field_interface_type, field_size) = match size {
1368e8f4f862SAlex Crichton         FlagsSize::Size0 => (quote!(NOT USED), 0usize),
1369e8f4f862SAlex Crichton         FlagsSize::Size1 => (quote!(#internal::InterfaceType::U8), 1),
1370e8f4f862SAlex Crichton         FlagsSize::Size2 => (quote!(#internal::InterfaceType::U16), 2),
1371e8f4f862SAlex Crichton         FlagsSize::Size4Plus(_) => (quote!(#internal::InterfaceType::U32), 4),
1372e8f4f862SAlex Crichton     };
1373e8f4f862SAlex Crichton 
13742329ecc3SAlex Crichton     let expanded = quote! {
13752329ecc3SAlex Crichton         #[derive(Copy, Clone, Default)]
13762329ecc3SAlex Crichton         pub struct #name { #fields }
13772329ecc3SAlex Crichton 
13782329ecc3SAlex Crichton         impl #name {
13792329ecc3SAlex Crichton             #constants
13802329ecc3SAlex Crichton 
13812329ecc3SAlex Crichton             pub fn as_array(&self) -> [u32; #count] {
13822329ecc3SAlex Crichton                 #as_array
13832329ecc3SAlex Crichton             }
13842329ecc3SAlex Crichton 
13852329ecc3SAlex Crichton             pub fn empty() -> Self {
13862329ecc3SAlex Crichton                 Self::default()
13872329ecc3SAlex Crichton             }
13882329ecc3SAlex Crichton 
13892329ecc3SAlex Crichton             pub fn all() -> Self {
139081a89169SAlex Crichton                 use core::ops::Not;
13912329ecc3SAlex Crichton                 Self::default().not()
13922329ecc3SAlex Crichton             }
139356a981bdSDan Gohman 
139456a981bdSDan Gohman             pub fn contains(&self, other: Self) -> bool {
139556a981bdSDan Gohman                 *self & other == other
139656a981bdSDan Gohman             }
139756a981bdSDan Gohman 
139856a981bdSDan Gohman             pub fn intersects(&self, other: Self) -> bool {
139956a981bdSDan Gohman                 *self & other != Self::empty()
140056a981bdSDan Gohman             }
14012329ecc3SAlex Crichton         }
14022329ecc3SAlex Crichton 
140381a89169SAlex Crichton         impl core::cmp::PartialEq for #name {
14042329ecc3SAlex Crichton             fn eq(&self, rhs: &#name) -> bool {
14052329ecc3SAlex Crichton                 #eq
14062329ecc3SAlex Crichton             }
14072329ecc3SAlex Crichton         }
14082329ecc3SAlex Crichton 
140981a89169SAlex Crichton         impl core::cmp::Eq for #name { }
14102329ecc3SAlex Crichton 
141181a89169SAlex Crichton         impl core::fmt::Debug for #name {
141281a89169SAlex Crichton             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
14132329ecc3SAlex Crichton                 #internal::format_flags(&self.as_array(), &[#rust_names], f)
14142329ecc3SAlex Crichton             }
14152329ecc3SAlex Crichton         }
14162329ecc3SAlex Crichton 
141781a89169SAlex Crichton         impl core::ops::BitOr for #name {
14182329ecc3SAlex Crichton             type Output = #name;
14192329ecc3SAlex Crichton 
14202329ecc3SAlex Crichton             fn bitor(self, rhs: #name) -> #name {
14212329ecc3SAlex Crichton                 #bitor
14222329ecc3SAlex Crichton             }
14232329ecc3SAlex Crichton         }
14242329ecc3SAlex Crichton 
142581a89169SAlex Crichton         impl core::ops::BitOrAssign for #name {
14262329ecc3SAlex Crichton             fn bitor_assign(&mut self, rhs: #name) {
14272329ecc3SAlex Crichton                 #bitor_assign
14282329ecc3SAlex Crichton             }
14292329ecc3SAlex Crichton         }
14302329ecc3SAlex Crichton 
143181a89169SAlex Crichton         impl core::ops::BitAnd for #name {
14322329ecc3SAlex Crichton             type Output = #name;
14332329ecc3SAlex Crichton 
14342329ecc3SAlex Crichton             fn bitand(self, rhs: #name) -> #name {
14352329ecc3SAlex Crichton                 #bitand
14362329ecc3SAlex Crichton             }
14372329ecc3SAlex Crichton         }
14382329ecc3SAlex Crichton 
143981a89169SAlex Crichton         impl core::ops::BitAndAssign for #name {
14402329ecc3SAlex Crichton             fn bitand_assign(&mut self, rhs: #name) {
14412329ecc3SAlex Crichton                 #bitand_assign
14422329ecc3SAlex Crichton             }
14432329ecc3SAlex Crichton         }
14442329ecc3SAlex Crichton 
144581a89169SAlex Crichton         impl core::ops::BitXor for #name {
14462329ecc3SAlex Crichton             type Output = #name;
14472329ecc3SAlex Crichton 
14482329ecc3SAlex Crichton             fn bitxor(self, rhs: #name) -> #name {
14492329ecc3SAlex Crichton                 #bitxor
14502329ecc3SAlex Crichton             }
14512329ecc3SAlex Crichton         }
14522329ecc3SAlex Crichton 
145381a89169SAlex Crichton         impl core::ops::BitXorAssign for #name {
14542329ecc3SAlex Crichton             fn bitxor_assign(&mut self, rhs: #name) {
14552329ecc3SAlex Crichton                 #bitxor_assign
14562329ecc3SAlex Crichton             }
14572329ecc3SAlex Crichton         }
14582329ecc3SAlex Crichton 
145981a89169SAlex Crichton         impl core::ops::Not for #name {
14602329ecc3SAlex Crichton             type Output = #name;
14612329ecc3SAlex Crichton 
14622329ecc3SAlex Crichton             fn not(self) -> #name {
14632329ecc3SAlex Crichton                 #not
14642329ecc3SAlex Crichton             }
14652329ecc3SAlex Crichton         }
14662329ecc3SAlex Crichton 
14672329ecc3SAlex Crichton         #component_type_impl
14682329ecc3SAlex Crichton 
146944220746SAlex Crichton         unsafe impl #wt::component::Lower for #name {
14707dba8efdSNick Fitzgerald             fn linear_lower_to_flat<T>(
1471e8f4f862SAlex Crichton                 &self,
1472e8f4f862SAlex Crichton                 cx: &mut #internal::LowerContext<'_, T>,
1473e8f4f862SAlex Crichton                 _ty: #internal::InterfaceType,
147481a89169SAlex Crichton                 dst: &mut core::mem::MaybeUninit<Self::Lower>,
1475*96e19700SNick Fitzgerald             ) -> #wt::Result<()> {
1476e8f4f862SAlex Crichton                 #(
14777dba8efdSNick Fitzgerald                     self.#field_names.linear_lower_to_flat(
1478e8f4f862SAlex Crichton                         cx,
1479e8f4f862SAlex Crichton                         #field_interface_type,
1480e8f4f862SAlex Crichton                         #internal::map_maybe_uninit!(dst.#field_names),
1481e8f4f862SAlex Crichton                     )?;
1482e8f4f862SAlex Crichton                 )*
1483e8f4f862SAlex Crichton                 Ok(())
1484e8f4f862SAlex Crichton             }
14852329ecc3SAlex Crichton 
14867dba8efdSNick Fitzgerald             fn linear_lower_to_memory<T>(
1487e8f4f862SAlex Crichton                 &self,
1488e8f4f862SAlex Crichton                 cx: &mut #internal::LowerContext<'_, T>,
1489e8f4f862SAlex Crichton                 _ty: #internal::InterfaceType,
1490e8f4f862SAlex Crichton                 mut offset: usize
1491*96e19700SNick Fitzgerald             ) -> #wt::Result<()> {
149244220746SAlex Crichton                 debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0);
1493e8f4f862SAlex Crichton                 #(
14947dba8efdSNick Fitzgerald                     self.#field_names.linear_lower_to_memory(
1495e8f4f862SAlex Crichton                         cx,
1496e8f4f862SAlex Crichton                         #field_interface_type,
1497e8f4f862SAlex Crichton                         offset,
1498e8f4f862SAlex Crichton                     )?;
149981a89169SAlex Crichton                     offset += core::mem::size_of_val(&self.#field_names);
1500e8f4f862SAlex Crichton                 )*
1501e8f4f862SAlex Crichton                 Ok(())
1502e8f4f862SAlex Crichton             }
1503e8f4f862SAlex Crichton         }
1504e8f4f862SAlex Crichton 
150544220746SAlex Crichton         unsafe impl #wt::component::Lift for #name {
15067dba8efdSNick Fitzgerald             fn linear_lift_from_flat(
15075a6ed0fbSAlex Crichton                 cx: &mut #internal::LiftContext<'_>,
1508e8f4f862SAlex Crichton                 _ty: #internal::InterfaceType,
1509e8f4f862SAlex Crichton                 src: &Self::Lower,
1510*96e19700SNick Fitzgerald             ) -> #wt::Result<Self> {
1511e8f4f862SAlex Crichton                 Ok(Self {
1512e8f4f862SAlex Crichton                     #(
15137dba8efdSNick Fitzgerald                         #field_names: #wt::component::Lift::linear_lift_from_flat(
1514e8f4f862SAlex Crichton                             cx,
1515e8f4f862SAlex Crichton                             #field_interface_type,
1516e8f4f862SAlex Crichton                             &src.#field_names,
1517e8f4f862SAlex Crichton                         )?,
1518e8f4f862SAlex Crichton                     )*
1519e8f4f862SAlex Crichton                 })
1520e8f4f862SAlex Crichton             }
1521e8f4f862SAlex Crichton 
15227dba8efdSNick Fitzgerald             fn linear_lift_from_memory(
15235a6ed0fbSAlex Crichton                 cx: &mut #internal::LiftContext<'_>,
1524e8f4f862SAlex Crichton                 _ty: #internal::InterfaceType,
1525e8f4f862SAlex Crichton                 bytes: &[u8],
1526*96e19700SNick Fitzgerald             ) -> #wt::Result<Self> {
1527e8f4f862SAlex Crichton                 debug_assert!(
1528e8f4f862SAlex Crichton                     (bytes.as_ptr() as usize)
152944220746SAlex Crichton                         % (<Self as #wt::component::ComponentType>::ALIGN32 as usize)
1530e8f4f862SAlex Crichton                         == 0
1531e8f4f862SAlex Crichton                 );
1532e8f4f862SAlex Crichton                 #(
1533e8f4f862SAlex Crichton                     let (field, bytes) = bytes.split_at(#field_size);
15347dba8efdSNick Fitzgerald                     let #field_names = #wt::component::Lift::linear_lift_from_memory(
1535e8f4f862SAlex Crichton                         cx,
1536e8f4f862SAlex Crichton                         #field_interface_type,
1537e8f4f862SAlex Crichton                         field,
1538e8f4f862SAlex Crichton                     )?;
1539e8f4f862SAlex Crichton                 )*
1540e8f4f862SAlex Crichton                 Ok(Self { #(#field_names,)* })
1541e8f4f862SAlex Crichton             }
1542e8f4f862SAlex Crichton         }
15432329ecc3SAlex Crichton     };
15442329ecc3SAlex Crichton 
15452329ecc3SAlex Crichton     Ok(expanded)
15462329ecc3SAlex Crichton }
1547