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