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