use super::{
CountedList, CountedListWriter, CountedWriter, Deserialize, Error, Instructions, Serialize,
ValueType, VarUint32,
};
use crate::{elements::section::SectionReader, io};
use alloc::vec::Vec;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Func(u32);
impl Func {
pub fn new(type_ref: u32) -> Self {
Func(type_ref)
}
pub fn type_ref(&self) -> u32 {
self.0
}
pub fn type_ref_mut(&mut self) -> &mut u32 {
&mut self.0
}
}
impl Serialize for Func {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.0).serialize(writer)
}
}
impl Deserialize for Func {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(Func(VarUint32::deserialize(reader)?.into()))
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Local {
count: u32,
value_type: ValueType,
}
impl Local {
pub fn new(count: u32, value_type: ValueType) -> Self {
Local { count, value_type }
}
pub fn count(&self) -> u32 {
self.count
}
pub fn value_type(&self) -> ValueType {
self.value_type
}
}
impl Deserialize for Local {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let count = VarUint32::deserialize(reader)?;
let value_type = ValueType::deserialize(reader)?;
Ok(Local { count: count.into(), value_type })
}
}
impl Serialize for Local {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
VarUint32::from(self.count).serialize(writer)?;
self.value_type.serialize(writer)?;
Ok(())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct FuncBody {
locals: Vec<Local>,
instructions: Instructions,
}
impl FuncBody {
pub fn new(locals: Vec<Local>, instructions: Instructions) -> Self {
FuncBody { locals, instructions }
}
pub fn empty() -> Self {
FuncBody { locals: Vec::new(), instructions: Instructions::empty() }
}
pub fn locals(&self) -> &[Local] {
&self.locals
}
pub fn code(&self) -> &Instructions {
&self.instructions
}
pub fn locals_mut(&mut self) -> &mut Vec<Local> {
&mut self.locals
}
pub fn code_mut(&mut self) -> &mut Instructions {
&mut self.instructions
}
}
impl Deserialize for FuncBody {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let mut body_reader = SectionReader::new(reader)?;
let locals: Vec<Local> = CountedList::<Local>::deserialize(&mut body_reader)?.into_inner();
locals
.iter()
.try_fold(0u32, |acc, &Local { count, .. }| acc.checked_add(count))
.ok_or(Error::TooManyLocals)?;
let instructions = Instructions::deserialize(&mut body_reader)?;
body_reader.close()?;
Ok(FuncBody { locals, instructions })
}
}
impl Serialize for FuncBody {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut counted_writer = CountedWriter::new(writer);
let data = self.locals;
let counted_list =
CountedListWriter::<Local, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(&mut counted_writer)?;
let code = self.instructions;
code.serialize(&mut counted_writer)?;
counted_writer.done()?;
Ok(())
}
}