wasmtime/runtime/component/resources/ty.rs
1//! This module defines the `ResourceType` type in the public API of Wasmtime,
2//! which is all possible types of resources.
3
4use crate::runtime::vm::component::ComponentInstance;
5use crate::store::StoreId;
6use core::any::TypeId;
7use wasmtime_environ::component::{
8 AbstractResourceIndex, ComponentTypes, DefinedResourceIndex, ResourceIndex,
9};
10
11/// Representation of a resource type in the component model.
12///
13/// Resources are currently always represented as 32-bit integers but they have
14/// unique types across instantiations and the host. For example instantiating
15/// the same component twice means that defined resource types in the component
16/// will all be different. Values of this type can be compared to see if
17/// resources have the same type.
18///
19/// Resource types can also be defined on the host in addition to guests. On the
20/// host resource types are tied to a `T`, an arbitrary Rust type. Two host
21/// resource types are the same if they point to the same `T`.
22#[derive(Debug, Copy, Clone, PartialEq, Eq)]
23pub struct ResourceType {
24 kind: ResourceTypeKind,
25}
26
27impl ResourceType {
28 /// Creates a new host resource type corresponding to `T`.
29 ///
30 /// Note that `T` is a mostly a phantom type parameter here. It does not
31 /// need to reflect the actual storage of the resource `T`. For example this
32 /// is valid:
33 ///
34 /// ```rust
35 /// use wasmtime::component::ResourceType;
36 ///
37 /// struct Foo;
38 ///
39 /// let ty = ResourceType::host::<Foo>();
40 /// ```
41 ///
42 /// A resource type of type `ResourceType::host::<T>()` will match the type
43 /// of the value produced by `Resource::<T>::new_{own,borrow}`.
44 pub fn host<T: 'static>() -> ResourceType {
45 ResourceType {
46 kind: ResourceTypeKind::Host(TypeId::of::<T>()),
47 }
48 }
49
50 /// Creates a new host resource type which is identified by the `payload`
51 /// runtime argument.
52 ///
53 /// The `payload` argument to this function is an arbitrary 32-bit value
54 /// that the host can use to distinguish one resource from another.
55 /// A resource type of type `ResourceType::host_dynamic(2)` will match the
56 /// type of the value produced by `ResourceDynamic::new_{own,borrow}(_, 2)`,
57 /// for example.
58 ///
59 /// This type of resource is disjoint from all other types of resources. For
60 /// example any resource with type `ResourceType::host::<u32>()` will be a
61 /// different type than all types created by this function.
62 pub fn host_dynamic(payload: u32) -> ResourceType {
63 ResourceType {
64 kind: ResourceTypeKind::HostDynamic(payload),
65 }
66 }
67
68 pub(crate) fn guest(
69 store: StoreId,
70 instance: &ComponentInstance,
71 id: DefinedResourceIndex,
72 ) -> ResourceType {
73 ResourceType {
74 kind: ResourceTypeKind::Guest {
75 store,
76 instance: instance as *const _ as usize,
77 id,
78 },
79 }
80 }
81
82 pub(crate) fn uninstantiated(types: &ComponentTypes, index: ResourceIndex) -> ResourceType {
83 ResourceType {
84 kind: ResourceTypeKind::Uninstantiated {
85 component: types as *const _ as usize,
86 index,
87 },
88 }
89 }
90
91 pub(crate) fn abstract_(types: &ComponentTypes, index: AbstractResourceIndex) -> ResourceType {
92 ResourceType {
93 kind: ResourceTypeKind::Abstract {
94 component: types as *const _ as usize,
95 index,
96 },
97 }
98 }
99
100 pub(crate) fn is_host<T: 'static>(&self) -> bool {
101 match self.kind {
102 ResourceTypeKind::Host(id) if id == TypeId::of::<T>() => true,
103 _ => false,
104 }
105 }
106
107 pub(crate) fn as_host_dynamic(&self) -> Option<u32> {
108 match self.kind {
109 ResourceTypeKind::HostDynamic(payload) => Some(payload),
110 _ => None,
111 }
112 }
113}
114
115#[derive(Debug, Copy, Clone, PartialEq, Eq)]
116enum ResourceTypeKind {
117 Host(TypeId),
118 HostDynamic(u32),
119 Guest {
120 store: StoreId,
121 // For now this is the `*mut ComponentInstance` pointer within the store
122 // that this guest corresponds to. It's used to distinguish different
123 // instantiations of the same component within the store.
124 instance: usize,
125 id: DefinedResourceIndex,
126 },
127 Uninstantiated {
128 // Like `instance` in `Guest` above this is a pointer and is used to
129 // distinguish between two components. Technically susceptible to ABA
130 // issues but the consequence is a nonexistent resource would be equal
131 // to a new resource so there's not really any issue with that.
132 component: usize,
133 index: ResourceIndex,
134 },
135 /// The type of this resource is considered "abstract" meaning that it
136 /// doesn't actually correspond to anything at runtime but instead it just
137 /// needs to be kept distinct from everything but itself.
138 Abstract {
139 component: usize,
140 index: AbstractResourceIndex,
141 },
142}