Path: blob/main/crates/wizer/src/component/snapshot.rs
3072 views
use wasmparser::ValType;12use crate::component::info::Accessor;3use crate::component::{ComponentContext, ComponentInstanceState, WIZER_INSTANCE};4use crate::snapshot::Snapshot;5use crate::{InstanceState, SnapshotVal};67/// Snapshot result of a component.8///9/// Currently this only contains the state for instances found within the10/// component, and each instance's snapshot is defined as the same core wasm11/// snapshot state.12pub struct ComponentSnapshot {13/// List of snapshots for corresponding module indices.14///15/// Note that modules don't get a snapshot if they aren't instantiated.16pub(crate) modules: Vec<(u32, Snapshot)>,17}1819pub async fn snapshot(20component: &ComponentContext<'_>,21ctx: &mut impl ComponentInstanceState,22) -> ComponentSnapshot {23let mut modules = Vec::new();2425for (module_index, module) in component.core_modules() {26// Ignore uninstantiated modules.27if !component.core_instantiations.contains_key(&module_index) {28continue;29}3031// Use the core-level snapshotting routines to collect a32// snapshot of the module. Requests for core-level items are33// redirected through the component-level `ctx` provided.34let snapshot = crate::snapshot::snapshot(35module,36&mut ViaComponent {37ctx,38module_index,39component,40},41)42.await;43modules.push((module_index, snapshot));44}4546ComponentSnapshot { modules }47}4849/// Implementation of `InstanceState` via component model primitives.50struct ViaComponent<'a, 'b, S> {51ctx: &'a mut S,52component: &'a ComponentContext<'b>,53module_index: u32,54}5556impl<'a, S> ViaComponent<'a, '_, S>57where58S: ComponentInstanceState,59{60fn get_accessor(&self, name: &str) -> &'a Accessor {61let accessors = self.component.accessors.as_ref().unwrap();62accessors63.iter()64.find(|a| match a {65Accessor::Global {66module_index,67core_export_name,68..69}70| Accessor::Memory {71module_index,72core_export_name,73..74} => *module_index == self.module_index && core_export_name == name,75})76.unwrap()77}78}7980impl<S> InstanceState for ViaComponent<'_, '_, S>81where82S: ComponentInstanceState,83{84async fn global_get(&mut self, name: &str, _: ValType) -> SnapshotVal {85let Accessor::Global {86accessor_export_name,87ty,88..89} = self.get_accessor(name)90else {91panic!("expected global accessor for {name}");92};93match ty {94wasmparser::ValType::I32 => SnapshotVal::I32(95self.ctx96.call_func_ret_s32(WIZER_INSTANCE, accessor_export_name)97.await,98),99wasmparser::ValType::I64 => SnapshotVal::I64(100self.ctx101.call_func_ret_s64(WIZER_INSTANCE, accessor_export_name)102.await,103),104wasmparser::ValType::F32 => SnapshotVal::F32(105self.ctx106.call_func_ret_f32(WIZER_INSTANCE, accessor_export_name)107.await,108),109wasmparser::ValType::F64 => SnapshotVal::F64(110self.ctx111.call_func_ret_f64(WIZER_INSTANCE, accessor_export_name)112.await,113),114wasmparser::ValType::V128 => todo!(),115wasmparser::ValType::Ref(_) => unreachable!(),116}117}118119async fn memory_contents(&mut self, name: &str, contents: impl FnOnce(&[u8]) + Send) {120let Accessor::Memory {121accessor_export_name,122..123} = self.get_accessor(name)124else {125panic!("expected memory accessor for {name}");126};127self.ctx128.call_func_ret_list_u8(WIZER_INSTANCE, accessor_export_name, contents)129.await130}131}132133134