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( 460 quote!(#ident: <#ty as #wt::component::Lift>::linear_lift_from_flat( 461 cx, #field_ty, &src.#ident 462 )?,), 463 ); 464 465 loads.extend( 466 quote!(#ident: <#ty as #wt::component::Lift>::linear_lift_from_memory( 467 cx, #field_ty, 468 &bytes 469 [<#ty as #wt::component::ComponentType>::ABI.next_field32_size(&mut offset)..] 470 [..<#ty as #wt::component::ComponentType>::SIZE32] 471 )?,), 472 ); 473 } 474 475 let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lift)); 476 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 477 478 let extract_ty = quote! { 479 let ty = match ty { 480 #internal::InterfaceType::Record(i) => &cx.types[i], 481 _ => #internal::bad_type_info(), 482 }; 483 }; 484 485 let expanded = quote! { 486 unsafe impl #impl_generics #wt::component::Lift for #name #ty_generics #where_clause { 487 #[inline] 488 fn linear_lift_from_flat( 489 cx: &mut #internal::LiftContext<'_>, 490 ty: #internal::InterfaceType, 491 src: &Self::Lower, 492 ) -> #internal::anyhow::Result<Self> { 493 #extract_ty 494 Ok(Self { 495 #lifts 496 }) 497 } 498 499 #[inline] 500 fn linear_lift_from_memory( 501 cx: &mut #internal::LiftContext<'_>, 502 ty: #internal::InterfaceType, 503 bytes: &[u8], 504 ) -> #internal::anyhow::Result<Self> { 505 #extract_ty 506 debug_assert!( 507 (bytes.as_ptr() as usize) 508 % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) 509 == 0 510 ); 511 let mut offset = 0; 512 Ok(Self { 513 #loads 514 }) 515 } 516 } 517 }; 518 519 Ok(expanded) 520 } 521 522 fn expand_variant( 523 &self, 524 name: &syn::Ident, 525 generics: &syn::Generics, 526 discriminant_size: DiscriminantSize, 527 cases: &[VariantCase], 528 wt: &syn::Path, 529 ) -> Result<TokenStream> { 530 let internal = quote!(#wt::component::__internal); 531 532 let mut lifts = TokenStream::new(); 533 let mut loads = TokenStream::new(); 534 535 for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() { 536 let index_u32 = u32::try_from(index).unwrap(); 537 538 let index_quoted = quote(discriminant_size, index); 539 540 if let Some(ty) = ty { 541 let payload_ty = quote!(ty.cases[#index].unwrap_or_else(#internal::bad_type_info)); 542 lifts.extend( 543 quote!(#index_u32 => Self::#ident(<#ty as #wt::component::Lift>::linear_lift_from_flat( 544 cx, #payload_ty, unsafe { &src.payload.#ident } 545 )?),), 546 ); 547 548 loads.extend( 549 quote!(#index_quoted => Self::#ident(<#ty as #wt::component::Lift>::linear_lift_from_memory( 550 cx, #payload_ty, &payload[..<#ty as #wt::component::ComponentType>::SIZE32] 551 )?),), 552 ); 553 } else { 554 lifts.extend(quote!(#index_u32 => Self::#ident,)); 555 556 loads.extend(quote!(#index_quoted => Self::#ident,)); 557 } 558 } 559 560 let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lift)); 561 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 562 563 let from_bytes = match discriminant_size { 564 DiscriminantSize::Size1 => quote!(bytes[0]), 565 DiscriminantSize::Size2 => quote!(u16::from_le_bytes(bytes[0..2].try_into()?)), 566 DiscriminantSize::Size4 => quote!(u32::from_le_bytes(bytes[0..4].try_into()?)), 567 }; 568 569 let extract_ty = quote! { 570 let ty = match ty { 571 #internal::InterfaceType::Variant(i) => &cx.types[i], 572 _ => #internal::bad_type_info(), 573 }; 574 }; 575 576 let expanded = quote! { 577 unsafe impl #impl_generics #wt::component::Lift for #name #ty_generics #where_clause { 578 #[inline] 579 fn linear_lift_from_flat( 580 cx: &mut #internal::LiftContext<'_>, 581 ty: #internal::InterfaceType, 582 src: &Self::Lower, 583 ) -> #internal::anyhow::Result<Self> { 584 #extract_ty 585 Ok(match src.tag.get_u32() { 586 #lifts 587 discrim => #internal::anyhow::bail!("unexpected discriminant: {}", discrim), 588 }) 589 } 590 591 #[inline] 592 fn linear_lift_from_memory( 593 cx: &mut #internal::LiftContext<'_>, 594 ty: #internal::InterfaceType, 595 bytes: &[u8], 596 ) -> #internal::anyhow::Result<Self> { 597 let align = <Self as #wt::component::ComponentType>::ALIGN32; 598 debug_assert!((bytes.as_ptr() as usize) % (align as usize) == 0); 599 let discrim = #from_bytes; 600 let payload_offset = <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32; 601 let payload = &bytes[payload_offset..]; 602 #extract_ty 603 Ok(match discrim { 604 #loads 605 discrim => #internal::anyhow::bail!("unexpected discriminant: {}", discrim), 606 }) 607 } 608 } 609 }; 610 611 Ok(expanded) 612 } 613 614 fn expand_enum( 615 &self, 616 name: &syn::Ident, 617 discriminant_size: DiscriminantSize, 618 cases: &[VariantCase], 619 wt: &syn::Path, 620 ) -> Result<TokenStream> { 621 let internal = quote!(#wt::component::__internal); 622 623 let (from_bytes, discrim_ty) = match discriminant_size { 624 DiscriminantSize::Size1 => (quote!(bytes[0]), quote!(u8)), 625 DiscriminantSize::Size2 => ( 626 quote!(u16::from_le_bytes(bytes[0..2].try_into()?)), 627 quote!(u16), 628 ), 629 DiscriminantSize::Size4 => ( 630 quote!(u32::from_le_bytes(bytes[0..4].try_into()?)), 631 quote!(u32), 632 ), 633 }; 634 let discrim_limit = proc_macro2::Literal::u32_suffixed(cases.len().try_into().unwrap()); 635 636 let extract_ty = quote! { 637 let ty = match ty { 638 #internal::InterfaceType::Enum(i) => &cx.types[i], 639 _ => #internal::bad_type_info(), 640 }; 641 }; 642 643 let expanded = quote! { 644 unsafe impl #wt::component::Lift for #name { 645 #[inline] 646 fn linear_lift_from_flat( 647 cx: &mut #internal::LiftContext<'_>, 648 ty: #internal::InterfaceType, 649 src: &Self::Lower, 650 ) -> #internal::anyhow::Result<Self> { 651 #extract_ty 652 let discrim = src.tag.get_u32(); 653 if discrim >= #discrim_limit { 654 #internal::anyhow::bail!("unexpected discriminant: {discrim}"); 655 } 656 Ok(unsafe { 657 #internal::transmute::<#discrim_ty, #name>(discrim as #discrim_ty) 658 }) 659 } 660 661 #[inline] 662 fn linear_lift_from_memory( 663 cx: &mut #internal::LiftContext<'_>, 664 ty: #internal::InterfaceType, 665 bytes: &[u8], 666 ) -> #internal::anyhow::Result<Self> { 667 let align = <Self as #wt::component::ComponentType>::ALIGN32; 668 debug_assert!((bytes.as_ptr() as usize) % (align as usize) == 0); 669 let discrim = #from_bytes; 670 if u32::from(discrim) >= #discrim_limit { 671 #internal::anyhow::bail!("unexpected discriminant: {discrim}"); 672 } 673 Ok(unsafe { 674 #internal::transmute::<#discrim_ty, #name>(discrim) 675 }) 676 } 677 } 678 }; 679 680 Ok(expanded) 681 } 682 } 683 684 pub struct LowerExpander; 685 686 impl Expander for LowerExpander { 687 fn expand_record( 688 &self, 689 name: &syn::Ident, 690 generics: &syn::Generics, 691 fields: &[&syn::Field], 692 wt: &syn::Path, 693 ) -> Result<TokenStream> { 694 let internal = quote!(#wt::component::__internal); 695 696 let mut lowers = TokenStream::new(); 697 let mut stores = TokenStream::new(); 698 699 for (i, syn::Field { ident, ty, .. }) in fields.iter().enumerate() { 700 let field_ty = quote!(ty.fields[#i].ty); 701 lowers.extend(quote!(#wt::component::Lower::linear_lower_to_flat( 702 &self.#ident, cx, #field_ty, #internal::map_maybe_uninit!(dst.#ident) 703 )?;)); 704 705 stores.extend(quote!(#wt::component::Lower::linear_lower_to_memory( 706 &self.#ident, 707 cx, 708 #field_ty, 709 <#ty as #wt::component::ComponentType>::ABI.next_field32_size(&mut offset), 710 )?;)); 711 } 712 713 let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lower)); 714 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 715 716 let extract_ty = quote! { 717 let ty = match ty { 718 #internal::InterfaceType::Record(i) => &cx.types[i], 719 _ => #internal::bad_type_info(), 720 }; 721 }; 722 723 let expanded = quote! { 724 unsafe impl #impl_generics #wt::component::Lower for #name #ty_generics #where_clause { 725 #[inline] 726 fn linear_lower_to_flat<T>( 727 &self, 728 cx: &mut #internal::LowerContext<'_, T>, 729 ty: #internal::InterfaceType, 730 dst: &mut core::mem::MaybeUninit<Self::Lower>, 731 ) -> #internal::anyhow::Result<()> { 732 #extract_ty 733 #lowers 734 Ok(()) 735 } 736 737 #[inline] 738 fn linear_lower_to_memory<T>( 739 &self, 740 cx: &mut #internal::LowerContext<'_, T>, 741 ty: #internal::InterfaceType, 742 mut offset: usize 743 ) -> #internal::anyhow::Result<()> { 744 debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0); 745 #extract_ty 746 #stores 747 Ok(()) 748 } 749 } 750 }; 751 752 Ok(expanded) 753 } 754 755 fn expand_variant( 756 &self, 757 name: &syn::Ident, 758 generics: &syn::Generics, 759 discriminant_size: DiscriminantSize, 760 cases: &[VariantCase], 761 wt: &syn::Path, 762 ) -> Result<TokenStream> { 763 let internal = quote!(#wt::component::__internal); 764 765 let mut lowers = TokenStream::new(); 766 let mut stores = TokenStream::new(); 767 768 for (index, VariantCase { ident, ty, .. }) in cases.iter().enumerate() { 769 let index_u32 = u32::try_from(index).unwrap(); 770 771 let index_quoted = quote(discriminant_size, index); 772 773 let discriminant_size = usize::from(discriminant_size); 774 775 let pattern; 776 let lower; 777 let store; 778 779 if ty.is_some() { 780 let ty = quote!(ty.cases[#index].unwrap_or_else(#internal::bad_type_info)); 781 pattern = quote!(Self::#ident(value)); 782 lower = quote!(value.linear_lower_to_flat(cx, #ty, dst)); 783 store = quote!(value.linear_lower_to_memory( 784 cx, 785 #ty, 786 offset + <Self as #internal::ComponentVariant>::PAYLOAD_OFFSET32, 787 )); 788 } else { 789 pattern = quote!(Self::#ident); 790 lower = quote!(Ok(())); 791 store = quote!(Ok(())); 792 } 793 794 lowers.extend(quote!(#pattern => { 795 #internal::map_maybe_uninit!(dst.tag).write(#wt::ValRaw::u32(#index_u32)); 796 unsafe { 797 #internal::lower_payload( 798 #internal::map_maybe_uninit!(dst.payload), 799 |payload| #internal::map_maybe_uninit!(payload.#ident), 800 |dst| #lower, 801 ) 802 } 803 })); 804 805 stores.extend(quote!(#pattern => { 806 *cx.get::<#discriminant_size>(offset) = #index_quoted.to_le_bytes(); 807 #store 808 })); 809 } 810 811 let generics = add_trait_bounds(generics, parse_quote!(#wt::component::Lower)); 812 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 813 814 let extract_ty = quote! { 815 let ty = match ty { 816 #internal::InterfaceType::Variant(i) => &cx.types[i], 817 _ => #internal::bad_type_info(), 818 }; 819 }; 820 821 let expanded = quote! { 822 unsafe impl #impl_generics #wt::component::Lower for #name #ty_generics #where_clause { 823 #[inline] 824 fn linear_lower_to_flat<T>( 825 &self, 826 cx: &mut #internal::LowerContext<'_, T>, 827 ty: #internal::InterfaceType, 828 dst: &mut core::mem::MaybeUninit<Self::Lower>, 829 ) -> #internal::anyhow::Result<()> { 830 #extract_ty 831 match self { 832 #lowers 833 } 834 } 835 836 #[inline] 837 fn linear_lower_to_memory<T>( 838 &self, 839 cx: &mut #internal::LowerContext<'_, T>, 840 ty: #internal::InterfaceType, 841 mut offset: usize 842 ) -> #internal::anyhow::Result<()> { 843 #extract_ty 844 debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0); 845 match self { 846 #stores 847 } 848 } 849 } 850 }; 851 852 Ok(expanded) 853 } 854 855 fn expand_enum( 856 &self, 857 name: &syn::Ident, 858 discriminant_size: DiscriminantSize, 859 _cases: &[VariantCase], 860 wt: &syn::Path, 861 ) -> Result<TokenStream> { 862 let internal = quote!(#wt::component::__internal); 863 864 let extract_ty = quote! { 865 let ty = match ty { 866 #internal::InterfaceType::Enum(i) => &cx.types[i], 867 _ => #internal::bad_type_info(), 868 }; 869 }; 870 871 let (size, ty) = match discriminant_size { 872 DiscriminantSize::Size1 => (1, quote!(u8)), 873 DiscriminantSize::Size2 => (2, quote!(u16)), 874 DiscriminantSize::Size4 => (4, quote!(u32)), 875 }; 876 let size = proc_macro2::Literal::usize_unsuffixed(size); 877 878 let expanded = quote! { 879 unsafe impl #wt::component::Lower for #name { 880 #[inline] 881 fn linear_lower_to_flat<T>( 882 &self, 883 cx: &mut #internal::LowerContext<'_, T>, 884 ty: #internal::InterfaceType, 885 dst: &mut core::mem::MaybeUninit<Self::Lower>, 886 ) -> #internal::anyhow::Result<()> { 887 #extract_ty 888 #internal::map_maybe_uninit!(dst.tag) 889 .write(#wt::ValRaw::u32(*self as u32)); 890 Ok(()) 891 } 892 893 #[inline] 894 fn linear_lower_to_memory<T>( 895 &self, 896 cx: &mut #internal::LowerContext<'_, T>, 897 ty: #internal::InterfaceType, 898 mut offset: usize 899 ) -> #internal::anyhow::Result<()> { 900 #extract_ty 901 debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0); 902 let discrim = *self as #ty; 903 *cx.get::<#size>(offset) = discrim.to_le_bytes(); 904 Ok(()) 905 } 906 } 907 }; 908 909 Ok(expanded) 910 } 911 } 912 913 pub struct ComponentTypeExpander; 914 915 impl Expander for ComponentTypeExpander { 916 fn expand_record( 917 &self, 918 name: &syn::Ident, 919 generics: &syn::Generics, 920 fields: &[&syn::Field], 921 wt: &syn::Path, 922 ) -> Result<TokenStream> { 923 expand_record_for_component_type( 924 name, 925 generics, 926 fields, 927 quote!(typecheck_record), 928 fields 929 .iter() 930 .map( 931 |syn::Field { 932 attrs, ident, ty, .. 933 }| { 934 let name = find_rename(attrs)?.unwrap_or_else(|| { 935 let ident = ident.as_ref().unwrap(); 936 syn::LitStr::new(&ident.to_string(), ident.span()) 937 }); 938 939 Ok(quote!((#name, <#ty as #wt::component::ComponentType>::typecheck),)) 940 }, 941 ) 942 .collect::<Result<_>>()?, 943 wt, 944 ) 945 } 946 947 fn expand_variant( 948 &self, 949 name: &syn::Ident, 950 generics: &syn::Generics, 951 _discriminant_size: DiscriminantSize, 952 cases: &[VariantCase], 953 wt: &syn::Path, 954 ) -> Result<TokenStream> { 955 let internal = quote!(#wt::component::__internal); 956 957 let mut case_names_and_checks = TokenStream::new(); 958 let mut lower_payload_generic_params = TokenStream::new(); 959 let mut lower_payload_generic_args = TokenStream::new(); 960 let mut lower_payload_case_declarations = TokenStream::new(); 961 let mut lower_generic_args = TokenStream::new(); 962 let mut abi_list = TokenStream::new(); 963 let mut unique_types = HashSet::new(); 964 965 for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() { 966 let rename = find_rename(attrs)?; 967 968 let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span())); 969 970 if let Some(ty) = ty { 971 abi_list.extend(quote!(Some(<#ty as #wt::component::ComponentType>::ABI),)); 972 973 case_names_and_checks.extend( 974 quote!((#name, Some(<#ty as #wt::component::ComponentType>::typecheck)),), 975 ); 976 977 let generic = format_ident!("T{}", index); 978 979 lower_payload_generic_params.extend(quote!(#generic: Copy,)); 980 lower_payload_generic_args.extend(quote!(#generic,)); 981 lower_payload_case_declarations.extend(quote!(#ident: #generic,)); 982 lower_generic_args.extend(quote!(<#ty as #wt::component::ComponentType>::Lower,)); 983 984 unique_types.insert(ty); 985 } else { 986 abi_list.extend(quote!(None,)); 987 case_names_and_checks.extend(quote!((#name, None),)); 988 lower_payload_case_declarations.extend(quote!(#ident: [#wt::ValRaw; 0],)); 989 } 990 } 991 992 let generics = add_trait_bounds(generics, parse_quote!(#wt::component::ComponentType)); 993 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); 994 let lower = format_ident!("Lower{}", name); 995 let lower_payload = format_ident!("LowerPayload{}", name); 996 997 // You may wonder why we make the types of all the fields of the #lower struct and #lower_payload union 998 // generic. This is to work around a [normalization bug in 999 // rustc](https://github.com/rust-lang/rust/issues/90903) such that the compiler does not understand that 1000 // e.g. `<i32 as ComponentType>::Lower` is `Copy` despite the bound specified in `ComponentType`'s 1001 // definition. 1002 // 1003 // See also the comment in `Self::expand_record` above for another reason why we do this. 1004 1005 let expanded = quote! { 1006 #[doc(hidden)] 1007 #[derive(Clone, Copy)] 1008 #[repr(C)] 1009 pub struct #lower<#lower_payload_generic_params> { 1010 tag: #wt::ValRaw, 1011 payload: #lower_payload<#lower_payload_generic_args> 1012 } 1013 1014 #[doc(hidden)] 1015 #[allow(non_snake_case)] 1016 #[derive(Clone, Copy)] 1017 #[repr(C)] 1018 union #lower_payload<#lower_payload_generic_params> { 1019 #lower_payload_case_declarations 1020 } 1021 1022 unsafe impl #impl_generics #wt::component::ComponentType for #name #ty_generics #where_clause { 1023 type Lower = #lower<#lower_generic_args>; 1024 1025 #[inline] 1026 fn typecheck( 1027 ty: &#internal::InterfaceType, 1028 types: &#internal::InstanceType<'_>, 1029 ) -> #internal::anyhow::Result<()> { 1030 #internal::typecheck_variant(ty, types, &[#case_names_and_checks]) 1031 } 1032 1033 const ABI: #internal::CanonicalAbiInfo = 1034 #internal::CanonicalAbiInfo::variant_static(&[#abi_list]); 1035 } 1036 1037 unsafe impl #impl_generics #internal::ComponentVariant for #name #ty_generics #where_clause { 1038 const CASES: &'static [Option<#internal::CanonicalAbiInfo>] = &[#abi_list]; 1039 } 1040 }; 1041 1042 Ok(quote!(const _: () = { #expanded };)) 1043 } 1044 1045 fn expand_enum( 1046 &self, 1047 name: &syn::Ident, 1048 _discriminant_size: DiscriminantSize, 1049 cases: &[VariantCase], 1050 wt: &syn::Path, 1051 ) -> Result<TokenStream> { 1052 let internal = quote!(#wt::component::__internal); 1053 1054 let mut case_names = TokenStream::new(); 1055 let mut abi_list = TokenStream::new(); 1056 1057 for VariantCase { attrs, ident, ty } in cases.iter() { 1058 let rename = find_rename(attrs)?; 1059 1060 let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span())); 1061 1062 if ty.is_some() { 1063 return Err(Error::new( 1064 ident.span(), 1065 "payloads are not permitted for `enum` cases", 1066 )); 1067 } 1068 abi_list.extend(quote!(None,)); 1069 case_names.extend(quote!(#name,)); 1070 } 1071 1072 let lower = format_ident!("Lower{}", name); 1073 1074 let cases_len = cases.len(); 1075 let expanded = quote! { 1076 #[doc(hidden)] 1077 #[derive(Clone, Copy)] 1078 #[repr(C)] 1079 pub struct #lower { 1080 tag: #wt::ValRaw, 1081 } 1082 1083 unsafe impl #wt::component::ComponentType for #name { 1084 type Lower = #lower; 1085 1086 #[inline] 1087 fn typecheck( 1088 ty: &#internal::InterfaceType, 1089 types: &#internal::InstanceType<'_>, 1090 ) -> #internal::anyhow::Result<()> { 1091 #internal::typecheck_enum(ty, types, &[#case_names]) 1092 } 1093 1094 const ABI: #internal::CanonicalAbiInfo = 1095 #internal::CanonicalAbiInfo::enum_(#cases_len); 1096 } 1097 1098 unsafe impl #internal::ComponentVariant for #name { 1099 const CASES: &'static [Option<#internal::CanonicalAbiInfo>] = &[#abi_list]; 1100 } 1101 }; 1102 1103 Ok(quote!(const _: () = { #expanded };)) 1104 } 1105 } 1106 1107 #[derive(Debug)] 1108 struct Flag { 1109 rename: Option<String>, 1110 name: String, 1111 } 1112 1113 impl Parse for Flag { 1114 fn parse(input: ParseStream) -> Result<Self> { 1115 let attributes = syn::Attribute::parse_outer(input)?; 1116 1117 let rename = find_rename(&attributes)?.map(|literal| literal.value()); 1118 1119 input.parse::<Token![const]>()?; 1120 let name = input.parse::<syn::Ident>()?.to_string(); 1121 1122 Ok(Self { rename, name }) 1123 } 1124 } 1125 1126 #[derive(Debug)] 1127 pub struct Flags { 1128 name: String, 1129 flags: Vec<Flag>, 1130 } 1131 1132 impl Parse for Flags { 1133 fn parse(input: ParseStream) -> Result<Self> { 1134 let name = input.parse::<syn::Ident>()?.to_string(); 1135 1136 let content; 1137 braced!(content in input); 1138 1139 let flags = content 1140 .parse_terminated(Flag::parse, Token![;])? 1141 .into_iter() 1142 .collect(); 1143 1144 Ok(Self { name, flags }) 1145 } 1146 } 1147 1148 pub fn expand_flags(flags: &Flags) -> Result<TokenStream> { 1149 let wt = default_wasmtime_crate(); 1150 let size = FlagsSize::from_count(flags.flags.len()); 1151 1152 let ty; 1153 let eq; 1154 1155 let count = flags.flags.len(); 1156 1157 match size { 1158 FlagsSize::Size0 => { 1159 ty = quote!(()); 1160 eq = quote!(true); 1161 } 1162 FlagsSize::Size1 => { 1163 ty = quote!(u8); 1164 1165 eq = if count == 8 { 1166 quote!(self.__inner0.eq(&rhs.__inner0)) 1167 } else { 1168 let mask = !(0xFF_u8 << count); 1169 1170 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask))) 1171 }; 1172 } 1173 FlagsSize::Size2 => { 1174 ty = quote!(u16); 1175 1176 eq = if count == 16 { 1177 quote!(self.__inner0.eq(&rhs.__inner0)) 1178 } else { 1179 let mask = !(0xFFFF_u16 << count); 1180 1181 quote!((self.__inner0 & #mask).eq(&(rhs.__inner0 & #mask))) 1182 }; 1183 } 1184 FlagsSize::Size4Plus(n) => { 1185 ty = quote!(u32); 1186 1187 let comparisons = (0..(n - 1)) 1188 .map(|index| { 1189 let field = format_ident!("__inner{}", index); 1190 1191 quote!(self.#field.eq(&rhs.#field) &&) 1192 }) 1193 .collect::<TokenStream>(); 1194 1195 let field = format_ident!("__inner{}", n - 1); 1196 1197 eq = if count % 32 == 0 { 1198 quote!(#comparisons self.#field.eq(&rhs.#field)) 1199 } else { 1200 let mask = !(0xFFFF_FFFF_u32 << (count % 32)); 1201 1202 quote!(#comparisons (self.#field & #mask).eq(&(rhs.#field & #mask))) 1203 } 1204 } 1205 } 1206 1207 let count; 1208 let mut as_array; 1209 let mut bitor; 1210 let mut bitor_assign; 1211 let mut bitand; 1212 let mut bitand_assign; 1213 let mut bitxor; 1214 let mut bitxor_assign; 1215 let mut not; 1216 1217 match size { 1218 FlagsSize::Size0 => { 1219 count = 0; 1220 as_array = quote!([]); 1221 bitor = quote!(Self {}); 1222 bitor_assign = quote!(); 1223 bitand = quote!(Self {}); 1224 bitand_assign = quote!(); 1225 bitxor = quote!(Self {}); 1226 bitxor_assign = quote!(); 1227 not = quote!(Self {}); 1228 } 1229 FlagsSize::Size1 | FlagsSize::Size2 => { 1230 count = 1; 1231 as_array = quote!([self.__inner0 as u32]); 1232 bitor = quote!(Self { 1233 __inner0: self.__inner0.bitor(rhs.__inner0) 1234 }); 1235 bitor_assign = quote!(self.__inner0.bitor_assign(rhs.__inner0)); 1236 bitand = quote!(Self { 1237 __inner0: self.__inner0.bitand(rhs.__inner0) 1238 }); 1239 bitand_assign = quote!(self.__inner0.bitand_assign(rhs.__inner0)); 1240 bitxor = quote!(Self { 1241 __inner0: self.__inner0.bitxor(rhs.__inner0) 1242 }); 1243 bitxor_assign = quote!(self.__inner0.bitxor_assign(rhs.__inner0)); 1244 not = quote!(Self { 1245 __inner0: self.__inner0.not() 1246 }); 1247 } 1248 FlagsSize::Size4Plus(n) => { 1249 count = usize::from(n); 1250 as_array = TokenStream::new(); 1251 bitor = TokenStream::new(); 1252 bitor_assign = TokenStream::new(); 1253 bitand = TokenStream::new(); 1254 bitand_assign = TokenStream::new(); 1255 bitxor = TokenStream::new(); 1256 bitxor_assign = TokenStream::new(); 1257 not = TokenStream::new(); 1258 1259 for index in 0..n { 1260 let field = format_ident!("__inner{}", index); 1261 1262 as_array.extend(quote!(self.#field,)); 1263 bitor.extend(quote!(#field: self.#field.bitor(rhs.#field),)); 1264 bitor_assign.extend(quote!(self.#field.bitor_assign(rhs.#field);)); 1265 bitand.extend(quote!(#field: self.#field.bitand(rhs.#field),)); 1266 bitand_assign.extend(quote!(self.#field.bitand_assign(rhs.#field);)); 1267 bitxor.extend(quote!(#field: self.#field.bitxor(rhs.#field),)); 1268 bitxor_assign.extend(quote!(self.#field.bitxor_assign(rhs.#field);)); 1269 not.extend(quote!(#field: self.#field.not(),)); 1270 } 1271 1272 as_array = quote!([#as_array]); 1273 bitor = quote!(Self { #bitor }); 1274 bitand = quote!(Self { #bitand }); 1275 bitxor = quote!(Self { #bitxor }); 1276 not = quote!(Self { #not }); 1277 } 1278 }; 1279 1280 let name = format_ident!("{}", flags.name); 1281 1282 let mut constants = TokenStream::new(); 1283 let mut rust_names = TokenStream::new(); 1284 let mut component_names = TokenStream::new(); 1285 1286 for (index, Flag { name, rename }) in flags.flags.iter().enumerate() { 1287 rust_names.extend(quote!(#name,)); 1288 1289 let component_name = rename.as_ref().unwrap_or(name); 1290 component_names.extend(quote!(#component_name,)); 1291 1292 let fields = match size { 1293 FlagsSize::Size0 => quote!(), 1294 FlagsSize::Size1 => { 1295 let init = 1_u8 << index; 1296 quote!(__inner0: #init) 1297 } 1298 FlagsSize::Size2 => { 1299 let init = 1_u16 << index; 1300 quote!(__inner0: #init) 1301 } 1302 FlagsSize::Size4Plus(n) => (0..n) 1303 .map(|i| { 1304 let field = format_ident!("__inner{}", i); 1305 1306 let init = if index / 32 == usize::from(i) { 1307 1_u32 << (index % 32) 1308 } else { 1309 0 1310 }; 1311 1312 quote!(#field: #init,) 1313 }) 1314 .collect::<TokenStream>(), 1315 }; 1316 1317 let name = format_ident!("{}", name); 1318 1319 constants.extend(quote!(pub const #name: Self = Self { #fields };)); 1320 } 1321 1322 let generics = syn::Generics { 1323 lt_token: None, 1324 params: Punctuated::new(), 1325 gt_token: None, 1326 where_clause: None, 1327 }; 1328 1329 let fields = { 1330 let ty = syn::parse2::<syn::Type>(ty.clone())?; 1331 1332 (0..count) 1333 .map(|index| syn::Field { 1334 attrs: Vec::new(), 1335 vis: syn::Visibility::Inherited, 1336 ident: Some(format_ident!("__inner{}", index)), 1337 colon_token: None, 1338 ty: ty.clone(), 1339 mutability: syn::FieldMutability::None, 1340 }) 1341 .collect::<Vec<_>>() 1342 }; 1343 1344 let fields = fields.iter().collect::<Vec<_>>(); 1345 1346 let component_type_impl = expand_record_for_component_type( 1347 &name, 1348 &generics, 1349 &fields, 1350 quote!(typecheck_flags), 1351 component_names, 1352 &wt, 1353 )?; 1354 1355 let internal = quote!(#wt::component::__internal); 1356 1357 let field_names = fields 1358 .iter() 1359 .map(|syn::Field { ident, .. }| ident) 1360 .collect::<Vec<_>>(); 1361 1362 let fields = fields 1363 .iter() 1364 .map(|syn::Field { ident, .. }| quote!(#[doc(hidden)] #ident: #ty,)) 1365 .collect::<TokenStream>(); 1366 1367 let (field_interface_type, field_size) = match size { 1368 FlagsSize::Size0 => (quote!(NOT USED), 0usize), 1369 FlagsSize::Size1 => (quote!(#internal::InterfaceType::U8), 1), 1370 FlagsSize::Size2 => (quote!(#internal::InterfaceType::U16), 2), 1371 FlagsSize::Size4Plus(_) => (quote!(#internal::InterfaceType::U32), 4), 1372 }; 1373 1374 let expanded = quote! { 1375 #[derive(Copy, Clone, Default)] 1376 pub struct #name { #fields } 1377 1378 impl #name { 1379 #constants 1380 1381 pub fn as_array(&self) -> [u32; #count] { 1382 #as_array 1383 } 1384 1385 pub fn empty() -> Self { 1386 Self::default() 1387 } 1388 1389 pub fn all() -> Self { 1390 use core::ops::Not; 1391 Self::default().not() 1392 } 1393 1394 pub fn contains(&self, other: Self) -> bool { 1395 *self & other == other 1396 } 1397 1398 pub fn intersects(&self, other: Self) -> bool { 1399 *self & other != Self::empty() 1400 } 1401 } 1402 1403 impl core::cmp::PartialEq for #name { 1404 fn eq(&self, rhs: &#name) -> bool { 1405 #eq 1406 } 1407 } 1408 1409 impl core::cmp::Eq for #name { } 1410 1411 impl core::fmt::Debug for #name { 1412 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 1413 #internal::format_flags(&self.as_array(), &[#rust_names], f) 1414 } 1415 } 1416 1417 impl core::ops::BitOr for #name { 1418 type Output = #name; 1419 1420 fn bitor(self, rhs: #name) -> #name { 1421 #bitor 1422 } 1423 } 1424 1425 impl core::ops::BitOrAssign for #name { 1426 fn bitor_assign(&mut self, rhs: #name) { 1427 #bitor_assign 1428 } 1429 } 1430 1431 impl core::ops::BitAnd for #name { 1432 type Output = #name; 1433 1434 fn bitand(self, rhs: #name) -> #name { 1435 #bitand 1436 } 1437 } 1438 1439 impl core::ops::BitAndAssign for #name { 1440 fn bitand_assign(&mut self, rhs: #name) { 1441 #bitand_assign 1442 } 1443 } 1444 1445 impl core::ops::BitXor for #name { 1446 type Output = #name; 1447 1448 fn bitxor(self, rhs: #name) -> #name { 1449 #bitxor 1450 } 1451 } 1452 1453 impl core::ops::BitXorAssign for #name { 1454 fn bitxor_assign(&mut self, rhs: #name) { 1455 #bitxor_assign 1456 } 1457 } 1458 1459 impl core::ops::Not for #name { 1460 type Output = #name; 1461 1462 fn not(self) -> #name { 1463 #not 1464 } 1465 } 1466 1467 #component_type_impl 1468 1469 unsafe impl #wt::component::Lower for #name { 1470 fn linear_lower_to_flat<T>( 1471 &self, 1472 cx: &mut #internal::LowerContext<'_, T>, 1473 _ty: #internal::InterfaceType, 1474 dst: &mut core::mem::MaybeUninit<Self::Lower>, 1475 ) -> #internal::anyhow::Result<()> { 1476 #( 1477 self.#field_names.linear_lower_to_flat( 1478 cx, 1479 #field_interface_type, 1480 #internal::map_maybe_uninit!(dst.#field_names), 1481 )?; 1482 )* 1483 Ok(()) 1484 } 1485 1486 fn linear_lower_to_memory<T>( 1487 &self, 1488 cx: &mut #internal::LowerContext<'_, T>, 1489 _ty: #internal::InterfaceType, 1490 mut offset: usize 1491 ) -> #internal::anyhow::Result<()> { 1492 debug_assert!(offset % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) == 0); 1493 #( 1494 self.#field_names.linear_lower_to_memory( 1495 cx, 1496 #field_interface_type, 1497 offset, 1498 )?; 1499 offset += core::mem::size_of_val(&self.#field_names); 1500 )* 1501 Ok(()) 1502 } 1503 } 1504 1505 unsafe impl #wt::component::Lift for #name { 1506 fn linear_lift_from_flat( 1507 cx: &mut #internal::LiftContext<'_>, 1508 _ty: #internal::InterfaceType, 1509 src: &Self::Lower, 1510 ) -> #internal::anyhow::Result<Self> { 1511 Ok(Self { 1512 #( 1513 #field_names: #wt::component::Lift::linear_lift_from_flat( 1514 cx, 1515 #field_interface_type, 1516 &src.#field_names, 1517 )?, 1518 )* 1519 }) 1520 } 1521 1522 fn linear_lift_from_memory( 1523 cx: &mut #internal::LiftContext<'_>, 1524 _ty: #internal::InterfaceType, 1525 bytes: &[u8], 1526 ) -> #internal::anyhow::Result<Self> { 1527 debug_assert!( 1528 (bytes.as_ptr() as usize) 1529 % (<Self as #wt::component::ComponentType>::ALIGN32 as usize) 1530 == 0 1531 ); 1532 #( 1533 let (field, bytes) = bytes.split_at(#field_size); 1534 let #field_names = #wt::component::Lift::linear_lift_from_memory( 1535 cx, 1536 #field_interface_type, 1537 field, 1538 )?; 1539 )* 1540 Ok(Self { #(#field_names,)* }) 1541 } 1542 } 1543 }; 1544 1545 Ok(expanded) 1546 } 1547