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