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