spin_factors/
runtime_factors.rs

1use wasmtime::component::{Linker, ResourceTable};
2
3use crate::{factor::FactorInstanceState, App, ConfiguredApp, Factor};
4
5/// A collection of `Factor`s that are initialized and configured together.
6///
7/// Implemented by `#[derive(RuntimeFactors)]` and should not be implemented manually.
8///
9/// # Example
10///
11/// A typical usage of `RuntimeFactors` would look something like the following pseudo-code:
12///
13/// ```ignore
14/// #[derive(RuntimeFactors)]
15/// struct MyFactors {
16///  // ...
17/// }
18/// // Initialize the factors collection
19/// let factors = MyFactors { /* .. */ };
20/// // Initialize each factor with a linker
21/// factors.init(&mut linker)?;
22/// // Configure the factors with an app and runtime config
23/// let configured_app = factors.configure_app(app, runtime_config)?;
24/// // Prepare instance state builders
25/// let builders = factors.prepare(&configured_app, "component-id")?;
26/// // Build the instance state for the factors
27/// let data = factors.build_instance_state(builders)?;
28/// // Initialize a `wasmtime` store with the instance state
29/// let mut store = wasmtime::Store::new(&engine, data);
30/// // Instantiate the component
31/// let instance = linker.instantiate_async(&mut store, &component).await?;
32/// ```
33pub trait RuntimeFactors: Send + Sync + Sized + 'static {
34    /// The per application state of all the factors.
35    type AppState: Sync + Send;
36    /// The per instance state of the factors.
37    type InstanceState: RuntimeFactorsInstanceState;
38    /// The collection of all the `InstanceBuilder`s of the factors.
39    type InstanceBuilders: Send + HasInstanceBuilder;
40    /// The runtime configuration of all the factors.
41    type RuntimeConfig: Default;
42
43    /// Initialize the factors with the given linker.
44    ///
45    /// Each factor's `init` is called in turn. Must be called once before
46    /// [`RuntimeFactors::prepare`].
47    fn init<T: AsInstanceState<Self::InstanceState> + Send + 'static>(
48        &mut self,
49        linker: &mut Linker<T>,
50    ) -> crate::Result<()>;
51
52    /// Configure the factors with the given app and runtime config.
53    fn configure_app(
54        &self,
55        app: App,
56        runtime_config: Self::RuntimeConfig,
57    ) -> crate::Result<ConfiguredApp<Self>>;
58
59    /// Prepare the factors' instance state builders.
60    fn prepare(
61        &self,
62        configured_app: &ConfiguredApp<Self>,
63        component_id: &str,
64    ) -> crate::Result<Self::InstanceBuilders>;
65
66    /// Build the instance state for the factors.
67    fn build_instance_state(
68        &self,
69        builders: Self::InstanceBuilders,
70    ) -> crate::Result<Self::InstanceState>;
71
72    /// Get the app state related to a particular factor.
73    fn app_state<F: Factor>(app_state: &Self::AppState) -> Option<&F::AppState>;
74
75    /// Get the instance builder of a particular factor.
76    ///
77    /// The outer `Option` is `None` if the factor has not been registered with this `Factors` collection,
78    /// and the inner `Option` is `None` if the factor has not been prepared yet.
79    fn instance_builder_mut<F: Factor>(
80        builders: &mut Self::InstanceBuilders,
81    ) -> Option<Option<&mut F::InstanceBuilder>>;
82}
83
84/// Allows querying an `InstanceBuilders` for a particular `Factor`'s `InstanceBuilder`.
85pub trait HasInstanceBuilder {
86    /// Get the instance builder of a particular factor.
87    fn for_factor<F: Factor>(&mut self) -> Option<&mut F::InstanceBuilder>;
88}
89
90/// Get the state of a particular Factor from the overall InstanceState
91///
92/// Implemented by `#[derive(RuntimeFactors)]`
93pub trait RuntimeFactorsInstanceState: AsInstanceState<Self> + Send + 'static {
94    fn get_with_table<F: Factor>(
95        &mut self,
96    ) -> Option<(&mut FactorInstanceState<F>, &mut ResourceTable)>;
97
98    fn get<F: Factor>(&mut self) -> Option<&mut FactorInstanceState<F>> {
99        self.get_with_table::<F>().map(|(state, _)| state)
100    }
101
102    fn table(&self) -> &ResourceTable;
103
104    fn table_mut(&mut self) -> &mut ResourceTable;
105}
106
107pub trait AsInstanceState<T: RuntimeFactorsInstanceState + ?Sized> {
108    fn as_instance_state(&mut self) -> &mut T;
109}