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