use super::RuntimeBlob;
struct SavedValue<Global> {
handle: Global,
value: sp_wasm_interface::Value,
}
pub trait InstanceGlobals {
type Global: Clone;
fn get_global(&mut self, export_name: &str) -> Self::Global;
fn get_global_value(&mut self, global: &Self::Global) -> sp_wasm_interface::Value;
fn set_global_value(&mut self, global: &Self::Global, value: sp_wasm_interface::Value);
}
pub struct ExposedMutableGlobalsSet(Vec<String>);
impl ExposedMutableGlobalsSet {
pub fn collect(runtime_blob: &RuntimeBlob) -> Self {
let global_names =
runtime_blob.exported_internal_global_names().map(ToOwned::to_owned).collect();
Self(global_names)
}
}
pub struct GlobalsSnapshot<Global>(Vec<SavedValue<Global>>);
impl<Global> GlobalsSnapshot<Global> {
pub fn take<Instance>(
mutable_globals: &ExposedMutableGlobalsSet,
instance: &mut Instance,
) -> Self
where
Instance: InstanceGlobals<Global = Global>,
{
let global_names = &mutable_globals.0;
let mut saved_values = Vec::with_capacity(global_names.len());
for global_name in global_names {
let handle = instance.get_global(global_name);
let value = instance.get_global_value(&handle);
saved_values.push(SavedValue { handle, value });
}
Self(saved_values)
}
pub fn apply<Instance>(&self, instance: &mut Instance)
where
Instance: InstanceGlobals<Global = Global>,
{
for saved_value in &self.0 {
instance.set_global_value(&saved_value.handle, saved_value.value);
}
}
}