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}