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