spin_factors/
prepare.rs

1use std::any::Any;
2
3use spin_app::AppComponent;
4
5use crate::{Error, Factor, RuntimeFactors};
6
7/// A builder for a [`Factor`]'s per instance state.
8pub trait FactorInstanceBuilder: Any {
9    /// The per instance state of the factor.
10    ///
11    /// This is equivalent to the existing `HostComponent::Data` and ends up
12    /// being stored in the `wasmtime::Store`. Any `bindgen` traits for this
13    /// factor will be implemented on this type.
14    type InstanceState: Send + 'static;
15
16    /// Build the per instance state of the factor.
17    fn build(self) -> anyhow::Result<Self::InstanceState>;
18}
19
20impl FactorInstanceBuilder for () {
21    type InstanceState = ();
22
23    fn build(self) -> anyhow::Result<Self::InstanceState> {
24        Ok(())
25    }
26}
27
28/// A helper trait for when the type implementing [`FactorInstanceBuilder`] is also the instance state.
29pub trait SelfInstanceBuilder: Send + 'static {}
30
31impl<T: SelfInstanceBuilder> FactorInstanceBuilder for T {
32    type InstanceState = Self;
33
34    fn build(self) -> anyhow::Result<Self::InstanceState> {
35        Ok(self)
36    }
37}
38
39/// A PrepareContext is passed to [`Factor::prepare`].
40///
41/// This gives the factor access to app state and the app component.
42pub struct PrepareContext<'a, T: RuntimeFactors, F: Factor> {
43    pub(crate) app_state: &'a F::AppState,
44    pub(crate) app_component: &'a AppComponent<'a>,
45    pub(crate) instance_builders: &'a mut T::InstanceBuilders,
46}
47
48impl<'a, T: RuntimeFactors, F: Factor> PrepareContext<'a, T, F> {
49    #[doc(hidden)]
50    pub fn new(
51        app_state: &'a F::AppState,
52        app_component: &'a AppComponent,
53        instance_builders: &'a mut T::InstanceBuilders,
54    ) -> Self {
55        Self {
56            app_state,
57            app_component,
58            instance_builders,
59        }
60    }
61
62    /// Get the app state related to the factor.
63    pub fn app_state(&self) -> &'a F::AppState {
64        self.app_state
65    }
66
67    /// Get the app component.
68    pub fn app_component(&self) -> &'a AppComponent {
69        self.app_component
70    }
71
72    /// Returns the prepared [`FactorInstanceBuilder`] for the given [`Factor`].
73    ///
74    /// Fails if the current [`RuntimeFactors`] does not include the given
75    /// [`Factor`] or if the given [`Factor`]'s builder has not been prepared
76    /// yet (because it is sequenced after this factor).
77    pub fn instance_builder<U: Factor>(&mut self) -> crate::Result<&mut U::InstanceBuilder> {
78        T::instance_builder_mut::<U>(self.instance_builders)
79            .ok_or(Error::no_such_factor::<U>())?
80            .ok_or_else(|| {
81                Error::DependencyOrderingError(format!(
82                    "{factor} builder requested before it was prepared",
83                    factor = std::any::type_name::<U>()
84                ))
85            })
86    }
87}