spin_factors/prepare.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
use std::any::Any;
use spin_app::AppComponent;
use crate::{Error, Factor, RuntimeFactors};
/// A builder for a [`Factor`]'s per instance state.
pub trait FactorInstanceBuilder: Any {
/// The per instance state of the factor.
///
/// This is equivalent to the existing `HostComponent::Data` and ends up
/// being stored in the `wasmtime::Store`. Any `bindgen` traits for this
/// factor will be implemented on this type.
type InstanceState: Send + 'static;
/// Build the per instance state of the factor.
fn build(self) -> anyhow::Result<Self::InstanceState>;
}
impl FactorInstanceBuilder for () {
type InstanceState = ();
fn build(self) -> anyhow::Result<Self::InstanceState> {
Ok(())
}
}
/// A helper trait for when the type implementing [`FactorInstanceBuilder`] is also the instance state.
pub trait SelfInstanceBuilder: Send + 'static {}
impl<T: SelfInstanceBuilder> FactorInstanceBuilder for T {
type InstanceState = Self;
fn build(self) -> anyhow::Result<Self::InstanceState> {
Ok(self)
}
}
/// A PrepareContext is passed to [`Factor::prepare`].
///
/// This gives the factor access to app state and the app component.
pub struct PrepareContext<'a, T: RuntimeFactors, F: Factor> {
pub(crate) app_state: &'a F::AppState,
pub(crate) app_component: &'a AppComponent<'a>,
pub(crate) instance_builders: &'a mut T::InstanceBuilders,
}
impl<'a, T: RuntimeFactors, F: Factor> PrepareContext<'a, T, F> {
#[doc(hidden)]
pub fn new(
app_state: &'a F::AppState,
app_component: &'a AppComponent,
instance_builders: &'a mut T::InstanceBuilders,
) -> Self {
Self {
app_state,
app_component,
instance_builders,
}
}
/// Get the app state related to the factor.
pub fn app_state(&self) -> &'a F::AppState {
self.app_state
}
/// Get the app component.
pub fn app_component(&self) -> &'a AppComponent {
self.app_component
}
/// Returns the prepared [`FactorInstanceBuilder`] for the given [`Factor`].
///
/// Fails if the current [`RuntimeFactors`] does not include the given
/// [`Factor`] or if the given [`Factor`]'s builder has not been prepared
/// yet (because it is sequenced after this factor).
pub fn instance_builder<U: Factor>(&mut self) -> crate::Result<&mut U::InstanceBuilder> {
T::instance_builder_mut::<U>(self.instance_builders)
.ok_or(Error::no_such_factor::<U>())?
.ok_or_else(|| {
Error::DependencyOrderingError(format!(
"{factor} builder requested before it was prepared",
factor = std::any::type_name::<U>()
))
})
}
}