use crate::ko::errors::FunctionSectionParseError;
use crate::ko::{Instr, SectionIdx};
use crate::{BufferIterator, WritableBuffer};
use std::slice::Iter;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct InstrIdx(u32);
impl From<usize> for InstrIdx {
fn from(i: usize) -> Self {
Self(i as u32)
}
}
impl From<u8> for InstrIdx {
fn from(i: u8) -> Self {
Self(i as u32)
}
}
impl From<u16> for InstrIdx {
fn from(i: u16) -> Self {
Self(i as u32)
}
}
impl From<u32> for InstrIdx {
fn from(i: u32) -> Self {
Self(i)
}
}
impl From<InstrIdx> for u32 {
fn from(instr_idx: InstrIdx) -> Self {
instr_idx.0
}
}
impl From<InstrIdx> for usize {
fn from(instr_idx: InstrIdx) -> Self {
instr_idx.0 as usize
}
}
#[derive(Debug)]
pub struct FuncSection {
instructions: Vec<Instr>,
size: u32,
section_index: SectionIdx,
}
impl FuncSection {
pub fn new(section_index: SectionIdx) -> Self {
Self {
instructions: Vec::new(),
size: 0,
section_index,
}
}
pub fn with_capacity(amount: usize, section_index: SectionIdx) -> Self {
Self {
instructions: Vec::with_capacity(amount),
size: 0,
section_index,
}
}
pub fn add(&mut self, instr: Instr) -> InstrIdx {
let index = self.instructions.len();
self.size += instr.size_bytes() as u32;
self.instructions.push(instr);
InstrIdx::from(index)
}
pub fn size(&self) -> u32 {
self.size
}
pub fn get(&self, index: InstrIdx) -> Option<&Instr> {
self.instructions.get(usize::from(index))
}
pub fn instructions(&self) -> Iter<Instr> {
self.instructions.iter()
}
pub fn section_index(&self) -> SectionIdx {
self.section_index
}
pub fn parse(
source: &mut BufferIterator,
size: u32,
section_index: SectionIdx,
) -> Result<Self, FunctionSectionParseError> {
let mut read_bytes = 0;
let mut instructions = Vec::new();
while read_bytes < size {
let instr = Instr::parse(source).map_err(|e| {
FunctionSectionParseError::InstrParseError(source.current_index(), e)
})?;
read_bytes += instr.size_bytes();
instructions.push(instr);
}
Ok(Self {
instructions,
size,
section_index,
})
}
pub fn write(&self, buf: &mut impl WritableBuffer) {
for instr in self.instructions.iter() {
instr.write(buf);
}
}
}