Path: blob/main/crates/wizer/src/component/snapshot.rs
2459 views
use crate::component::info::Accessor;1use crate::component::{ComponentContext, ComponentInstanceState, WIZER_INSTANCE};2use crate::snapshot::Snapshot;3use crate::{InstanceState, SnapshotVal};45/// Snapshot result of a component.6///7/// Currently this only contains the state for instances found within the8/// component, and each instance's snapshot is defined as the same core wasm9/// snapshot state.10pub struct ComponentSnapshot {11/// List of snapshots for corresponding module indices.12///13/// Note that modules don't get a snapshot if they aren't instantiated.14pub(crate) modules: Vec<(u32, Snapshot)>,15}1617pub async fn snapshot(18component: &ComponentContext<'_>,19ctx: &mut impl ComponentInstanceState,20) -> ComponentSnapshot {21let mut modules = Vec::new();2223for (module_index, module) in component.core_modules() {24// Ignore uninstantiated modules.25if !component.core_instantiations.contains_key(&module_index) {26continue;27}2829// Use the core-level snapshotting routines to collect a30// snapshot of the module. Requests for core-level items are31// redirected through the component-level `ctx` provided.32let snapshot = crate::snapshot::snapshot(33module,34&mut ViaComponent {35ctx,36module_index,37component,38},39)40.await;41modules.push((module_index, snapshot));42}4344ComponentSnapshot { modules }45}4647/// Implementation of `InstanceState` via component model primitives.48struct ViaComponent<'a, 'b, S> {49ctx: &'a mut S,50component: &'a ComponentContext<'b>,51module_index: u32,52}5354impl<'a, S> ViaComponent<'a, '_, S>55where56S: ComponentInstanceState,57{58fn get_accessor(&self, name: &str) -> &'a Accessor {59let accessors = self.component.accessors.as_ref().unwrap();60accessors61.iter()62.find(|a| match a {63Accessor::Global {64module_index,65core_export_name,66..67}68| Accessor::Memory {69module_index,70core_export_name,71..72} => *module_index == self.module_index && core_export_name == name,73})74.unwrap()75}76}7778impl<S> InstanceState for ViaComponent<'_, '_, S>79where80S: ComponentInstanceState,81{82async fn global_get(&mut self, name: &str) -> SnapshotVal {83let Accessor::Global {84accessor_export_name,85ty,86..87} = self.get_accessor(name)88else {89panic!("expected global accessor for {name}");90};91match ty {92wasmparser::ValType::I32 => SnapshotVal::I32(93self.ctx94.call_func_ret_s32(WIZER_INSTANCE, accessor_export_name)95.await,96),97wasmparser::ValType::I64 => SnapshotVal::I64(98self.ctx99.call_func_ret_s64(WIZER_INSTANCE, accessor_export_name)100.await,101),102wasmparser::ValType::F32 => SnapshotVal::F32(103self.ctx104.call_func_ret_f32(WIZER_INSTANCE, accessor_export_name)105.await,106),107wasmparser::ValType::F64 => SnapshotVal::F64(108self.ctx109.call_func_ret_f64(WIZER_INSTANCE, accessor_export_name)110.await,111),112wasmparser::ValType::V128 => todo!(),113wasmparser::ValType::Ref(_) => unreachable!(),114}115}116117async fn memory_contents(&mut self, name: &str, contents: impl FnOnce(&[u8]) + Send) {118let Accessor::Memory {119accessor_export_name,120..121} = self.get_accessor(name)122else {123panic!("expected memory accessor for {name}");124};125self.ctx126.call_func_ret_list_u8(WIZER_INSTANCE, accessor_export_name, contents)127.await128}129}130131132