use super::InstanceWrapper;
use tc_executor_common::error::{Result, Error};
use tetcore_wasm_interface::Value;
use crate::imports::{into_value, into_wasmtime_val};
struct SavedValue {
index: usize,
value: Value,
}
pub struct GlobalsSnapshot(Vec<SavedValue>);
impl GlobalsSnapshot {
pub fn take(instance_wrapper: &InstanceWrapper) -> Result<Self> {
let data = instance_wrapper.instance
.exports()
.enumerate()
.filter_map(|(index, export)| {
if export.name().starts_with("exported_internal_global") {
export.into_global().map(
|g| SavedValue { index, value: into_value(g.get()) }
)
} else { None }
})
.collect::<Vec<_>>();
Ok(Self(data))
}
pub fn apply(&self, instance_wrapper: &InstanceWrapper) -> Result<()> {
let mut current = 0;
for (index, export) in instance_wrapper.instance.exports().enumerate() {
if current >= self.0.len() { break; }
let current_saved = &self.0[current];
if index < current_saved.index { continue; }
else if index > current_saved.index { current += 1; continue; }
else {
export.into_global()
.ok_or_else(|| Error::Other(
"Wrong instance in GlobalsSnapshot::apply: what should be global is not global.".to_string()
))?
.set(into_wasmtime_val(current_saved.value))
.map_err(|_e| Error::Other(
"Wrong instance in GlobalsSnapshot::apply: global saved type does not matched applied.".to_string()
))?;
}
}
Ok(())
}
}