wasmi/module/instantiate/
pre.rs

1use super::InstantiationError;
2use crate::{module::FuncIdx, AsContextMut, Error, Instance, InstanceEntityBuilder};
3
4/// A partially instantiated [`Instance`] where the `start` function has not yet been executed.
5///
6/// # Note
7///
8/// Some users require Wasm modules to not have a `start` function that is required for
9/// conformant module instantiation. This API provides control over the precise instantiation
10/// process with regard to this need.
11#[derive(Debug)]
12pub struct InstancePre {
13    handle: Instance,
14    builder: InstanceEntityBuilder,
15}
16
17impl InstancePre {
18    /// Creates a new [`InstancePre`].
19    pub(super) fn new(handle: Instance, builder: InstanceEntityBuilder) -> Self {
20        Self { handle, builder }
21    }
22
23    /// Returns the index of the `start` function if any.
24    ///
25    /// Returns `None` if the Wasm module does not have a `start` function.
26    fn start_fn(&self) -> Option<u32> {
27        self.builder.get_start().map(FuncIdx::into_u32)
28    }
29
30    /// Runs the `start` function of the [`Instance`] and returns its handle.
31    ///
32    /// # Note
33    ///
34    /// This finishes the instantiation procedure.
35    ///
36    /// # Errors
37    ///
38    /// If executing the `start` function traps.
39    ///
40    /// # Panics
41    ///
42    /// If the `start` function is invalid albeit successful validation.
43    pub fn start(self, mut context: impl AsContextMut) -> Result<Instance, Error> {
44        let opt_start_index = self.start_fn();
45        context
46            .as_context_mut()
47            .store
48            .inner
49            .initialize_instance(self.handle, self.builder.finish());
50        if let Some(start_index) = opt_start_index {
51            let start_func = self
52                .handle
53                .get_func_by_index(&mut context, start_index)
54                .unwrap_or_else(|| {
55                    panic!("encountered invalid start function after validation: {start_index}")
56                });
57            start_func.call(context.as_context_mut(), &[], &mut [])?
58        }
59        Ok(self.handle)
60    }
61
62    /// Finishes instantiation ensuring that no `start` function exists.
63    ///
64    /// # Errors
65    ///
66    /// If a `start` function exists that needs to be called for conformant module instantiation.
67    pub fn ensure_no_start(
68        self,
69        mut context: impl AsContextMut,
70    ) -> Result<Instance, InstantiationError> {
71        if let Some(index) = self.start_fn() {
72            return Err(InstantiationError::FoundStartFn { index });
73        }
74        context
75            .as_context_mut()
76            .store
77            .inner
78            .initialize_instance(self.handle, self.builder.finish());
79        Ok(self.handle)
80    }
81}