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 /// Returns whether this type was defined by the host, as opposed to by a
108 /// guest or by an uninstantiated or abstract component type.
109 pub(crate) fn is_host_defined(&self) -> bool {
110 match self.kind {
111 ResourceTypeKind::Host(_) | ResourceTypeKind::HostDynamic(_) => true,
112 ResourceTypeKind::Guest { .. }
113 | ResourceTypeKind::Uninstantiated { .. }
114 | ResourceTypeKind::Abstract { .. } => false,
115 }
116 }
117
118 pub(crate) fn as_host_dynamic(&self) -> Option<u32> {
119 match self.kind {
120 ResourceTypeKind::HostDynamic(payload) => Some(payload),
121 _ => None,
122 }
123 }
124}
125
126#[derive(Debug, Copy, Clone, PartialEq, Eq)]
127enum ResourceTypeKind {
128 Host(TypeId),
129 HostDynamic(u32),
130 Guest {
131 store: StoreId,
132 // For now this is the `*mut ComponentInstance` pointer within the store
133 // that this guest corresponds to. It's used to distinguish different
134 // instantiations of the same component within the store.
135 instance: usize,
136 id: DefinedResourceIndex,
137 },
138 Uninstantiated {
139 // Like `instance` in `Guest` above this is a pointer and is used to
140 // distinguish between two components. Technically susceptible to ABA
141 // issues but the consequence is a nonexistent resource would be equal
142 // to a new resource so there's not really any issue with that.
143 component: usize,
144 index: ResourceIndex,
145 },
146 /// The type of this resource is considered "abstract" meaning that it
147 /// doesn't actually correspond to anything at runtime but instead it just
148 /// needs to be kept distinct from everything but itself.
149 Abstract {
150 component: usize,
151 index: AbstractResourceIndex,
152 },
153}