use alloc::{string::String, vec::Vec};
use core::mem;
use parity_wasm::elements::{self, Serialize};
use crate::{section::SectionKind, Error, Result, Section};
#[derive(Debug)]
pub struct Module(elements::Module);
impl Module {
pub fn new(buf: &[u8]) -> Result<Self> {
Ok(Module(elements::Module::from_bytes(buf).map_err(Error)?))
}
pub fn sections(&self) -> Result<impl Iterator<Item = Section<'_>>> {
const ERROR_MESSAGE: Error = Error::with_msg("Incorrect Section Order");
let mut kind = SectionKind::Name;
let iter = self.0.custom_sections();
for section in self.0.custom_sections() {
match section.name() {
"name" if kind <= SectionKind::Name => {
kind = SectionKind::Producers
}
"producers" if kind <= SectionKind::Producers => {
kind = SectionKind::Daku
}
"daku" if kind <= SectionKind::Daku => {
kind = SectionKind::Unknown
}
"name" | "producers" | "daku" => return Err(ERROR_MESSAGE),
_ => {}
}
}
Ok(iter.map(|section| Section::Any {
name: section.name().into(),
data: section.payload().into(),
}))
}
pub fn set_section(&mut self, mut section: Section<'_>) -> Option<()> {
let (name, data) = section.to_any()?;
self.0.set_custom_section(name, data.to_vec());
Some(())
}
pub fn clear_section(
&mut self,
name: impl AsRef<str>,
) -> Option<Section<'static>> {
let mut section = self.0.clear_custom_section(&name)?;
let (mut name, mut data) = (String::new(), Vec::new());
mem::swap(&mut name, section.name_mut());
mem::swap(&mut data, section.payload_mut());
Some(Section::Any {
name: name.into(),
data: data.into(),
})
}
pub fn into_buffer(self) -> Result<Vec<u8>> {
let mut v = Vec::new();
self.0.serialize(&mut v).map_err(Error)?;
Ok(v)
}
}