use getset::Getters;
use scroll::{ctx, Uleb128};
use crate::error;
#[allow(dead_code)]
#[derive(Debug, Getters, Default)]
#[get = "pub"]
struct TryBlock {
start_pc: u64,
length: u64,
num_catches: u64,
catch_blocks: Vec<(CatchBlock, usize)>,
}
impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for TryBlock {
type Error = error::Error;
fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
let off = &mut 0;
let start_pc = Uleb128::read(source, off).unwrap();
let length = Uleb128::read(source, off).unwrap();
let num_catches = Uleb128::read(source, off).unwrap();
let catch_blocks = (0..num_catches)
.map(|_| CatchBlock::try_from_ctx(source, scroll::Endian::Little))
.collect::<Result<Vec<_>, _>>()?;
Ok((
TryBlock {
start_pc,
length,
num_catches,
catch_blocks,
},
source.len(),
))
}
}
#[allow(dead_code)]
#[derive(Debug, Getters, Default)]
#[get = "pub"]
struct CatchBlock {
type_idx: u64,
handler_pc: u64,
catch_type: u64,
}
impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for CatchBlock {
type Error = error::Error;
fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
let off = &mut 0;
let type_idx = Uleb128::read(source, off).unwrap();
let handler_pc = Uleb128::read(source, off).unwrap();
let catch_type = Uleb128::read(source, off).unwrap();
Ok((
CatchBlock {
type_idx,
handler_pc,
catch_type,
},
source.len(),
))
}
}
#[derive(Debug, Getters, Default)]
#[get = "pub"]
pub struct Code {
num_regs: u64,
num_args: u64,
code_size: u64,
tries_size: u64,
instructions: Vec<u8>,
try_blocks: Vec<(TryBlock, usize)>,
}
impl<'a> ctx::TryFromCtx<'a, scroll::Endian> for Code {
type Error = error::Error;
fn try_from_ctx(source: &'a [u8], _: scroll::Endian) -> Result<(Self, usize), Self::Error> {
let off = &mut 0;
let num_regs = Uleb128::read(source, off).unwrap();
let num_args = Uleb128::read(source, off).unwrap();
let code_size = Uleb128::read(source, off).unwrap();
let tries_size = Uleb128::read(source, off).unwrap();
tracing::debug!(
"num_regs: {}, num_args: {}, code_size: {}, tries_size: {}",
num_regs,
num_args,
code_size,
tries_size
);
let instructions = source[*off..*off + code_size as usize].to_vec();
*off += code_size as usize;
let try_blocks = (0..tries_size)
.map(|_| TryBlock::try_from_ctx(source, scroll::Endian::Little))
.collect::<Result<Vec<_>, _>>()?;
Ok((
Code {
num_regs,
num_args,
code_size,
tries_size,
instructions,
try_blocks,
},
source.len(),
))
}
}