use alloc::vec::Vec;
use wasmparser::{DataKind, Operator, Parser, Payload};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExtractError {
BadWasm,
NoDataSection,
}
pub(crate) fn const_i32_offset(offset_expr: &wasmparser::ConstExpr) -> Option<i32> {
let mut ops = offset_expr.get_operators_reader();
match ops.read().ok()? {
Operator::I32Const { value } => Some(value),
_ => None,
}
}
pub fn extract_digs_segment(module: &[u8], mem_offset: u32) -> Result<Vec<u8>, ExtractError> {
let mut found: Option<Vec<u8>> = None;
for payload in Parser::new(0).parse_all(module) {
let payload = payload.map_err(|_| ExtractError::BadWasm)?;
if let Payload::DataSection(reader) = payload {
for seg in reader {
let seg = seg.map_err(|_| ExtractError::BadWasm)?;
let DataKind::Active { offset_expr, .. } = seg.kind else {
continue;
};
let Some(off) = const_i32_offset(&offset_expr) else {
continue;
};
if off as u32 == mem_offset && seg.data.len() >= 4 && &seg.data[..4] == b"DIGS" {
found = Some(seg.data.to_vec());
}
}
}
}
found.ok_or(ExtractError::NoDataSection)
}