use super::RuntimeBlob;
use crate::error::{self, Error};
use std::mem;
use wasm_instrument::parity_wasm::elements::Instruction;
#[derive(Clone)]
pub struct DataSegmentsSnapshot {
data_segments: Vec<(u32, Vec<u8>)>,
}
impl DataSegmentsSnapshot {
pub fn take(module: &RuntimeBlob) -> error::Result<Self> {
let data_segments = module
.data_segments()
.into_iter()
.map(|mut segment| {
let contents = mem::take(segment.value_mut());
let init_expr = match segment.offset() {
Some(offset) => offset.code(),
None => return Err(Error::SharedMemUnsupported),
};
if init_expr.len() != 2 {
return Err(Error::InitializerHasTooManyExpressions)
}
let offset = match &init_expr[0] {
Instruction::I32Const(v) => *v as u32,
Instruction::GetGlobal(_) => {
return Err(Error::ImportedGlobalsUnsupported)
},
insn => return Err(Error::InvalidInitializerExpression(format!("{:?}", insn))),
};
Ok((offset, contents))
})
.collect::<error::Result<Vec<_>>>()?;
Ok(Self { data_segments })
}
pub fn apply<E>(
&self,
mut memory_set: impl FnMut(u32, &[u8]) -> Result<(), E>,
) -> Result<(), E> {
for (offset, contents) in &self.data_segments {
memory_set(*offset, contents)?;
}
Ok(())
}
}