1use proc_macro2::{Span, TokenStream};
2use quote::{format_ident, quote};
3use std::collections::HashSet;
4use std::fmt;
5use syn::parse::{Parse, ParseStream};
6use syn::punctuated::Punctuated;
7use syn::{Data, DeriveInput, Error, Ident, Result, Token, braced, parse_quote};
8use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9
10mod 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)]
19enum Style {
20 Record,
21 Enum,
22 Variant,
23}
24
25impl 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)]
36enum ComponentAttr {
37 Style(Style),
38 WasmtimeCrate(syn::Path),
39}
40
41impl 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
68fn 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
94fn 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
104pub struct VariantCase<'a> {
105 attrs: &'a [syn::Attribute],
106 ident: &'a syn::Ident,
107 ty: Option<&'a syn::Type>,
108}
109
110pub 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
137pub 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
167fn default_wasmtime_crate() -> syn::Path {
168 Ident::new("wasmtime", Span::call_site()).into()
169}
170
171fn 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
202fn 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
290fn 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
347fn 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 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
425fn 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
442pub struct LiftExpander;
443
444impl 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::usize_unsuffixed(cases.len());
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 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
684pub struct LowerExpander;
685
686impl 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
913pub struct ComponentTypeExpander;
914
915impl 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 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)]
1108struct Flag {
1109 rename: Option<String>,
1110 name: String,
1111}
1112
1113impl 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)]
1127pub struct Flags {
1128 name: String,
1129 flags: Vec<Flag>,
1130}
1131
1132impl 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
1148pub 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}