use crate::{BinaryReader, FromReader, Result};
use crate::{Ieee32, Ieee64, prelude::*};
pub struct CoreDumpSection<'a> {
pub name: &'a str,
}
impl<'a> CoreDumpSection<'a> {
pub fn new(mut reader: BinaryReader<'a>) -> Result<CoreDumpSection<'a>> {
let pos = reader.original_position();
if reader.read_u8()? != 0 {
bail!(pos, "invalid start byte for core dump name");
}
let name = reader.read_unlimited_string()?;
if !reader.eof() {
bail!(
reader.original_position(),
"trailing bytes at end of custom section"
);
}
Ok(CoreDumpSection { name })
}
}
#[derive(Debug)]
pub struct CoreDumpModulesSection<'a> {
pub modules: Vec<&'a str>,
}
impl<'a> CoreDumpModulesSection<'a> {
pub fn new(mut reader: BinaryReader<'a>) -> Result<CoreDumpModulesSection<'a>> {
let pos = reader.original_position();
let mut modules = vec![];
for _ in 0..reader.read_var_u32()? {
if reader.read_u8()? != 0 {
bail!(pos, "invalid start byte for coremodule");
}
modules.push(reader.read_unlimited_string()?);
}
if !reader.eof() {
bail!(
reader.original_position(),
"trailing bytes at end of custom section"
);
}
Ok(CoreDumpModulesSection { modules })
}
}
pub struct CoreDumpInstancesSection {
pub instances: Vec<CoreDumpInstance>,
}
impl CoreDumpInstancesSection {
pub fn new(mut reader: BinaryReader<'_>) -> Result<CoreDumpInstancesSection> {
let mut instances = vec![];
for _ in 0..reader.read_var_u32()? {
instances.push(CoreDumpInstance::from_reader(&mut reader)?);
}
if !reader.eof() {
bail!(
reader.original_position(),
"trailing bytes at end of custom section"
);
}
Ok(CoreDumpInstancesSection { instances })
}
}
#[derive(Debug)]
pub struct CoreDumpInstance {
pub module_index: u32,
pub memories: Vec<u32>,
pub globals: Vec<u32>,
}
impl<'a> FromReader<'a> for CoreDumpInstance {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
let pos = reader.original_position();
if reader.read_u8()? != 0 {
bail!(pos, "invalid start byte for core dump instance");
}
let module_index = reader.read_var_u32()?;
let mut memories = vec![];
for _ in 0..reader.read_var_u32()? {
memories.push(reader.read_var_u32()?);
}
let mut globals = vec![];
for _ in 0..reader.read_var_u32()? {
globals.push(reader.read_var_u32()?);
}
Ok(CoreDumpInstance {
module_index,
memories,
globals,
})
}
}
pub struct CoreDumpStackSection<'a> {
pub name: &'a str,
pub frames: Vec<CoreDumpStackFrame>,
}
impl<'a> CoreDumpStackSection<'a> {
pub fn new(mut reader: BinaryReader<'a>) -> Result<CoreDumpStackSection<'a>> {
let pos = reader.original_position();
if reader.read_u8()? != 0 {
bail!(pos, "invalid start byte for core dump stack name");
}
let name = reader.read_unlimited_string()?;
let mut frames = vec![];
for _ in 0..reader.read_var_u32()? {
frames.push(CoreDumpStackFrame::from_reader(&mut reader)?);
}
if !reader.eof() {
bail!(
reader.original_position(),
"trailing bytes at end of custom section"
);
}
Ok(CoreDumpStackSection {
name: name,
frames: frames,
})
}
}
#[derive(Debug)]
pub struct CoreDumpStackFrame {
pub instanceidx: u32,
pub funcidx: u32,
pub codeoffset: u32,
pub locals: Vec<CoreDumpValue>,
pub stack: Vec<CoreDumpValue>,
}
impl<'a> FromReader<'a> for CoreDumpStackFrame {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
let pos = reader.original_position();
if reader.read_u8()? != 0 {
bail!(pos, "invalid start byte for core dump stack frame");
}
let instanceidx = reader.read_var_u32()?;
let funcidx = reader.read_var_u32()?;
let codeoffset = reader.read_var_u32()?;
let mut locals = vec![];
for _ in 0..reader.read_var_u32()? {
locals.push(CoreDumpValue::from_reader(reader)?);
}
let mut stack = vec![];
for _ in 0..reader.read_var_u32()? {
stack.push(CoreDumpValue::from_reader(reader)?);
}
Ok(CoreDumpStackFrame {
instanceidx,
funcidx,
codeoffset,
locals,
stack,
})
}
}
#[derive(Clone, Debug)]
pub enum CoreDumpValue {
Missing,
I32(i32),
I64(i64),
F32(Ieee32),
F64(Ieee64),
}
impl<'a> FromReader<'a> for CoreDumpValue {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
let pos = reader.original_position();
match reader.read_u8()? {
0x01 => Ok(CoreDumpValue::Missing),
0x7F => Ok(CoreDumpValue::I32(reader.read_var_i32()?)),
0x7E => Ok(CoreDumpValue::I64(reader.read_var_i64()?)),
0x7D => Ok(CoreDumpValue::F32(reader.read_f32()?)),
0x7C => Ok(CoreDumpValue::F64(reader.read_f64()?)),
_ => bail!(pos, "invalid CoreDumpValue type"),
}
}
}