Skip to content

Commit

Permalink
feat: implement ResourceAny -> Resource<T> conversion
Browse files Browse the repository at this point in the history
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
  • Loading branch information
rvolosatovs committed Dec 21, 2023
1 parent ab6d971 commit accf39c
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
31 changes: 31 additions & 0 deletions crates/wasmtime/src/component/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,32 @@ where
})
}

/// Attempts to convert a [`ResourceAny`] into [`Resource`].
pub fn try_from_resource_any(
ResourceAny { idx, ty, own_state }: ResourceAny,
mut store: impl AsContextMut,
) -> Result<Self> {
let store = store.as_context_mut();
let store_id = store.0.id();
let mut tables = host_resource_tables(store.0);
ensure!(ty == ResourceType::host::<T>(), "resource type mismatch");
let (state, rep) = if let Some(OwnState { store, dtor, flags }) = own_state {
ensure!(store_id == store, "wrong store used to convert resource");
ensure!(dtor.is_some(), "destructor must be set");
ensure!(flags.is_none(), "flags must not be set");
let rep = tables.resource_lift_own(None, idx)?;
(AtomicU32::new(NOT_IN_TABLE), rep)
} else {
let rep = tables.resource_lift_borrow(None, idx)?;
(AtomicU32::new(BORROW), rep)
};
Ok(Resource {
state,
rep,
_marker: marker::PhantomData,
})
}

/// See [`ResourceAny::try_from_resource`]
pub fn try_into_resource_any<U>(
self,
Expand Down Expand Up @@ -566,6 +592,11 @@ impl ResourceAny {
})
}

/// See [`Resource::try_from_resource_any`]
pub fn try_into_resource<T: 'static>(self, store: impl AsContextMut) -> Result<Resource<T>> {
Resource::try_from_resource_any(self, store)
}

/// Returns the corresponding type associated with this resource, either a
/// host-defined type or a guest-defined type.
///
Expand Down
38 changes: 36 additions & 2 deletions tests/all/component_model/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,15 @@ fn dynamic_val() -> Result<()> {
match &results[0] {
Val::Resource(resource) => {
assert_eq!(resource.ty(), ResourceType::host::<MyType>());
assert!(resource.owned());

let resource = resource.try_into_resource::<MyType>(&mut store)?;
assert_eq!(resource.rep(), 100);
assert!(resource.owned());

let resource = resource.try_into_resource_any(&mut store, &i_pre, idx)?;
assert_eq!(resource.ty(), ResourceType::host::<MyType>());
assert!(resource.owned());
}
_ => unreachable!(),
}
Expand All @@ -593,21 +602,46 @@ fn dynamic_val() -> Result<()> {
match &results[0] {
Val::Resource(resource) => {
assert_eq!(resource.ty(), ResourceType::host::<MyType>());
assert!(resource.owned());

let resource = resource.try_into_resource::<MyType>(&mut store)?;
assert_eq!(resource.rep(), 100);
assert!(resource.owned());

let resource = resource.try_into_resource_any(&mut store, &i_pre, idx)?;
assert_eq!(resource.ty(), ResourceType::host::<MyType>());
assert!(resource.owned());
}
_ => unreachable!(),
}

let t1 = Resource::new_own(100);
let t1 = Resource::<MyType>::new_own(100)
.try_into_resource_any(&mut store, &i_pre, idx)?
.try_into_resource(&mut store)?;
let (t1,) = a_typed_result.call(&mut store, (t1,))?;
a_typed_result.post_return(&mut store)?;
assert_eq!(t1.rep(), 100);
assert!(t1.owned());

let t1_any = t1.try_into_resource_any(&mut store, &i_pre, idx)?;
let t1_any = t1
.try_into_resource_any(&mut store, &i_pre, idx)?
.try_into_resource::<MyType>(&mut store)?
.try_into_resource_any(&mut store, &i_pre, idx)?;
let mut results = [Val::Bool(false)];
a.call(&mut store, &[Val::Resource(t1_any)], &mut results)?;
a.post_return(&mut store)?;
match &results[0] {
Val::Resource(resource) => {
assert_eq!(resource.ty(), ResourceType::host::<MyType>());
assert!(resource.owned());

let resource = resource.try_into_resource::<MyType>(&mut store)?;
assert_eq!(resource.rep(), 100);
assert!(resource.owned());

let resource = resource.try_into_resource_any(&mut store, &i_pre, idx)?;
assert_eq!(resource.ty(), ResourceType::host::<MyType>());
assert!(resource.owned());
}
_ => unreachable!(),
}
Expand Down

0 comments on commit accf39c

Please sign in to comment.