Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions crates/component-macro/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,15 @@ fn expand_record_for_component_type(
let mut lower_field_declarations = TokenStream::new();
let mut abi_list = TokenStream::new();
let mut unique_types = HashSet::new();

for (index, syn::Field { ident, ty, .. }) in fields.iter().enumerate() {
let mut field_as_vals = TokenStream::new();

for (
index,
syn::Field {
ident, ty, attrs, ..
},
) in fields.iter().enumerate()
{
let generic = format_ident!("T{}", index);

lower_generic_params.extend(quote!(#generic: Copy,));
Expand All @@ -373,6 +380,15 @@ fn expand_record_for_component_type(
));

unique_types.insert(ty);

let name = find_rename(attrs)?.unwrap_or_else(|| {
let ident = ident.as_ref().unwrap();
syn::LitStr::new(&ident.to_string(), ident.span())
});
field_as_vals.extend(quote!(
(#internal::String::from(#name),
#wt::component::ComponentType::as_val(&self.#ident, &mut store)? ),
));
}

let generics = add_trait_bounds(generics, parse_quote!(#wt::component::ComponentType));
Expand Down Expand Up @@ -416,6 +432,12 @@ fn expand_record_for_component_type(
) -> #wt::Result<()> {
#internal::#typecheck(ty, types, &[#typecheck_argument])
}

fn as_val(&self, mut store: impl #wt::AsContextMut) -> #wt::Result<#wt::component::Val> {
Ok(#wt::component::Val::Record(vec![
#field_as_vals
]))
}
}
};

Expand Down Expand Up @@ -961,10 +983,10 @@ impl Expander for ComponentTypeExpander {
let mut lower_generic_args = TokenStream::new();
let mut abi_list = TokenStream::new();
let mut unique_types = HashSet::new();
let mut as_val_cases = TokenStream::new();

for (index, VariantCase { attrs, ident, ty }) in cases.iter().enumerate() {
let rename = find_rename(attrs)?;

let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span()));

if let Some(ty) = ty {
Expand All @@ -982,10 +1004,17 @@ impl Expander for ComponentTypeExpander {
lower_generic_args.extend(quote!(<#ty as #wt::component::ComponentType>::Lower,));

unique_types.insert(ty);

as_val_cases.extend(quote!(
Self::#ident(inner) => (#internal::String::from(#name), Some(#internal::Box::new(inner.as_val(store)?))),
));
} else {
abi_list.extend(quote!(None,));
case_names_and_checks.extend(quote!((#name, None),));
lower_payload_case_declarations.extend(quote!(#ident: [#wt::ValRaw; 0],));
as_val_cases.extend(quote!(
Self::#ident => (#internal::String::from(#name), None),
));
}
}

Expand Down Expand Up @@ -1032,6 +1061,13 @@ impl Expander for ComponentTypeExpander {

const ABI: #internal::CanonicalAbiInfo =
#internal::CanonicalAbiInfo::variant_static(&[#abi_list]);

fn as_val(&self, mut store: impl #wt::AsContextMut) -> #wt::Result<#wt::component::Val> {
let (variant_name, opt_payload) = match self {
#as_val_cases
};
Ok(#wt::component::Val::Variant(variant_name, opt_payload))
}
}

unsafe impl #impl_generics #internal::ComponentVariant for #name #ty_generics #where_clause {
Expand All @@ -1053,10 +1089,10 @@ impl Expander for ComponentTypeExpander {

let mut case_names = TokenStream::new();
let mut abi_list = TokenStream::new();
let mut as_val_cases = TokenStream::new();

for VariantCase { attrs, ident, ty } in cases.iter() {
let rename = find_rename(attrs)?;

let name = rename.unwrap_or_else(|| syn::LitStr::new(&ident.to_string(), ident.span()));

if ty.is_some() {
Expand All @@ -1067,6 +1103,7 @@ impl Expander for ComponentTypeExpander {
}
abi_list.extend(quote!(None,));
case_names.extend(quote!(#name,));
as_val_cases.extend(quote!(Self::#ident => #internal::String::from(#name),));
}

let lower = format_ident!("Lower{}", name);
Expand All @@ -1093,6 +1130,10 @@ impl Expander for ComponentTypeExpander {

const ABI: #internal::CanonicalAbiInfo =
#internal::CanonicalAbiInfo::enum_(#cases_len);

fn as_val(&self, _: impl #wt::AsContextMut) -> #wt::Result<#wt::component::Val> {
Ok(#wt::component::Val::Enum(match self { #as_val_cases }))
}
}

unsafe impl #internal::ComponentVariant for #name {
Expand Down
4 changes: 4 additions & 0 deletions crates/test-util/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ macro_rules! forward_impls {
fn typecheck(ty: &InterfaceType, types: &InstanceType<'_>) -> Result<()> {
<$b as ComponentType>::typecheck(ty, types)
}

fn as_val(&self, store: impl AsContextMut) -> Result<Val> {
self.0.as_val(store)
}
}

unsafe impl Lower for $a {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::component::func::{LiftContext, LowerContext, bad_type_info, desc};
use crate::component::matching::InstanceType;
use crate::component::types::{self, FutureType, StreamType};
use crate::component::{
ComponentInstanceId, ComponentType, FutureReader, Lift, Lower, StreamReader,
ComponentInstanceId, ComponentType, FutureReader, Lift, Lower, StreamReader, Val,
};
use crate::store::StoreOpaque;
use crate::{AsContextMut, Result, bail, error::Context};
Expand Down Expand Up @@ -146,6 +146,10 @@ unsafe impl ComponentType for FutureAny {
other => bail!("expected `future`, found `{}`", desc(other)),
}
}

fn as_val(&self, _: impl AsContextMut) -> Result<Val> {
Ok(Val::Future(self.clone()))
}
}

unsafe impl Lower for FutureAny {
Expand Down Expand Up @@ -313,6 +317,10 @@ unsafe impl ComponentType for StreamAny {
other => bail!("expected `stream`, found `{}`", desc(other)),
}
}

fn as_val(&self, _: impl AsContextMut) -> Result<Val> {
Ok(Val::Stream(self.clone()))
}
}

unsafe impl Lower for StreamAny {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1376,7 +1376,7 @@ pub(super) fn lower_future_to_index<U>(

// SAFETY: This relies on the `ComponentType` implementation for `u32` being
// safe and correct since we lift and lower future handles as `u32`s.
unsafe impl<T: ComponentType> ComponentType for FutureReader<T> {
unsafe impl<T: ComponentType + 'static> ComponentType for FutureReader<T> {
const ABI: CanonicalAbiInfo = CanonicalAbiInfo::SCALAR4;

type Lower = <u32 as func::ComponentType>::Lower;
Expand All @@ -1390,10 +1390,20 @@ unsafe impl<T: ComponentType> ComponentType for FutureReader<T> {
other => bail!("expected `future`, found `{}`", func::desc(other)),
}
}

fn as_val(&self, store: impl AsContextMut) -> Result<Val> {
Ok(Val::Future(FutureAny::try_from_future_reader(
store,
FutureReader {
id: self.id,
_phantom: PhantomData::<T>,
},
)?))
}
}

// SAFETY: See the comment on the `ComponentType` `impl` for this type.
unsafe impl<T: ComponentType> func::Lower for FutureReader<T> {
unsafe impl<T: ComponentType + 'static> func::Lower for FutureReader<T> {
fn linear_lower_to_flat<U>(
&self,
cx: &mut LowerContext<'_, U>,
Expand All @@ -1418,7 +1428,7 @@ unsafe impl<T: ComponentType> func::Lower for FutureReader<T> {
}

// SAFETY: See the comment on the `ComponentType` `impl` for this type.
unsafe impl<T: ComponentType> func::Lift for FutureReader<T> {
unsafe impl<T: ComponentType + 'static> func::Lift for FutureReader<T> {
fn linear_lift_from_flat(
cx: &mut LiftContext<'_>,
ty: InterfaceType,
Expand Down Expand Up @@ -1723,7 +1733,7 @@ pub(super) fn lower_stream_to_index<U>(

// SAFETY: This relies on the `ComponentType` implementation for `u32` being
// safe and correct since we lift and lower stream handles as `u32`s.
unsafe impl<T: ComponentType> ComponentType for StreamReader<T> {
unsafe impl<T: ComponentType + 'static> ComponentType for StreamReader<T> {
const ABI: CanonicalAbiInfo = CanonicalAbiInfo::SCALAR4;

type Lower = <u32 as func::ComponentType>::Lower;
Expand All @@ -1737,10 +1747,20 @@ unsafe impl<T: ComponentType> ComponentType for StreamReader<T> {
other => bail!("expected `stream`, found `{}`", func::desc(other)),
}
}

fn as_val(&self, store: impl AsContextMut) -> Result<Val> {
Ok(Val::Stream(StreamAny::try_from_stream_reader(
store,
StreamReader {
id: self.id,
_phantom: PhantomData::<T>,
},
)?))
}
}

// SAFETY: See the comment on the `ComponentType` `impl` for this type.
unsafe impl<T: ComponentType> func::Lower for StreamReader<T> {
unsafe impl<T: ComponentType + 'static> func::Lower for StreamReader<T> {
fn linear_lower_to_flat<U>(
&self,
cx: &mut LowerContext<'_, U>,
Expand All @@ -1765,7 +1785,7 @@ unsafe impl<T: ComponentType> func::Lower for StreamReader<T> {
}

// SAFETY: See the comment on the `ComponentType` `impl` for this type.
unsafe impl<T: ComponentType> func::Lift for StreamReader<T> {
unsafe impl<T: ComponentType + 'static> func::Lift for StreamReader<T> {
fn linear_lift_from_flat(
cx: &mut LiftContext<'_>,
ty: InterfaceType,
Expand Down Expand Up @@ -1918,6 +1938,10 @@ unsafe impl func::ComponentType for ErrorContext {
other => bail!("expected `error`, found `{}`", func::desc(other)),
}
}

fn as_val(&self, _: impl AsContextMut) -> Result<Val> {
Ok(Val::ErrorContext(ErrorContextAny(self.rep)))
}
}

// SAFETY: See the comment on the `ComponentType` `impl` for this type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ unsafe impl ComponentType for FutureAny {
fn typecheck(_ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
bail!("support for component-model-async disabled at compile time")
}

fn as_val(&self, _: impl AsContextMut) -> Result<Val> {
bail!("support for component-model-async disabled at compile time")
}
}

unsafe impl Lift for FutureAny {
Expand Down Expand Up @@ -110,6 +114,10 @@ unsafe impl ComponentType for StreamAny {
fn typecheck(_ty: &InterfaceType, _types: &InstanceType<'_>) -> Result<()> {
bail!("support for component-model-async disabled at compile time")
}

fn as_val(&self, _: impl AsContextMut) -> Result<Val> {
bail!("support for component-model-async disabled at compile time")
}
}

unsafe impl Lift for StreamAny {
Expand Down
Loading
Loading