From 871398ff821255debdbd9452e46ca55a05e8cb92 Mon Sep 17 00:00:00 2001 From: Henry Gressmann Date: Fri, 1 Dec 2023 14:00:46 +0100 Subject: feat: wip: seperate parser and types crates Signed-off-by: Henry Gressmann --- crates/parser/src/module.rs | 181 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 crates/parser/src/module.rs (limited to 'crates/parser/src/module.rs') diff --git a/crates/parser/src/module.rs b/crates/parser/src/module.rs new file mode 100644 index 0000000..e2e1bde --- /dev/null +++ b/crates/parser/src/module.rs @@ -0,0 +1,181 @@ +use alloc::{format, vec::Vec}; +use core::fmt::Debug; +use tracing::debug; +use wasmparser::{ + ExportSectionReader, FunctionBody, FunctionSectionReader, Payload, TypeSectionReader, Validator, +}; + +use crate::{ParseError, Result}; + +#[derive(Default)] +pub struct ModuleReader<'a> { + pub version: Option, + pub start_func: Option, + + pub type_section: Option>, + pub function_section: Option>, + pub export_section: Option>, + pub code_section: Option>, + + // pub table_section: Option>, + // pub memory_section: Option>, + // pub global_section: Option>, + // pub element_section: Option>, + // pub data_section: Option>, + // pub import_section: Option>, + pub end_reached: bool, +} + +impl Debug for ModuleReader<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("ModuleReader") + .field("version", &self.version) + .field("type_section", &self.type_section) + .field("function_section", &self.function_section) + .field("code_section", &self.code_section) + .field("export_section", &self.export_section) + // .field("table_section", &self.table_section) + // .field("memory_section", &self.memory_section) + // .field("global_section", &self.global_section) + // .field("element_section", &self.element_section) + // .field("data_section", &self.data_section) + // .field("import_section", &self.import_section) + .finish() + } +} + +impl<'a> ModuleReader<'a> { + pub fn new() -> ModuleReader<'a> { + Self::default() + } + + pub fn process_payload( + &mut self, + payload: Payload<'a>, + validator: &mut Validator, + ) -> Result<()> { + use wasmparser::Payload::*; + + match payload { + Version { + num, + encoding, + range, + } => { + validator.version(num, encoding, &range)?; + self.version = Some(num); + match encoding { + wasmparser::Encoding::Module => {} + wasmparser::Encoding::Component => { + return Err(ParseError::InvalidEncoding(encoding)) + } + } + } + StartSection { func, range } => { + debug!("Found start section"); + validator.start_section(func, &range)?; + self.start_func = Some(func); + } + TypeSection(reader) => { + debug!("Found type section"); + validator.type_section(&reader)?; + self.type_section = Some(reader); + } + FunctionSection(reader) => { + debug!("Found function section"); + validator.function_section(&reader)?; + self.function_section = Some(reader); + } + TableSection(_reader) => { + return Err(ParseError::UnsupportedSection("Table section".into())); + // debug!("Found table section"); + // validator.table_section(&reader)?; + // self.table_section = Some(reader); + } + MemorySection(_reader) => { + return Err(ParseError::UnsupportedSection("Memory section".into())); + // debug!("Found memory section"); + // validator.memory_section(&reader)?; + // self.memory_section = Some(reader); + } + GlobalSection(_reader) => { + return Err(ParseError::UnsupportedSection("Global section".into())); + // debug!("Found global section"); + // validator.global_section(&reader)?; + // self.global_section = Some(reader); + } + ElementSection(_reader) => { + return Err(ParseError::UnsupportedSection("Element section".into())); + // debug!("Found element section"); + // validator.element_section(&reader)?; + // self.element_section = Some(reader); + } + DataSection(_reader) => { + return Err(ParseError::UnsupportedSection("Data section".into())); + // debug!("Found data section"); + // validator.data_section(&reader)?; + // self.data_section = Some(reader); + } + CodeSectionStart { count, range, .. } => { + debug!("Found code section ({} functions)", count); + if self.code_section.is_some() { + return Err(ParseError::DuplicateSection("Code section".into())); + } + + validator.code_section_start(count, &range)?; + self.code_section = Some(CodeSection::new()); + } + CodeSectionEntry(function) => { + debug!("Found code section entry"); + validator.code_section_entry(&function)?; + + if let Some(code_section) = &mut self.code_section { + code_section.functions.push(function); + } else { + return Err(ParseError::EmptySection("Code section".into())); + } + } + ImportSection(_reader) => { + return Err(ParseError::UnsupportedSection("Import section".into())); + + // debug!("Found import section"); + // validator.import_section(&reader)?; + // self.import_section = Some(reader); + } + ExportSection(reader) => { + debug!("Found export section"); + validator.export_section(&reader)?; + self.export_section = Some(reader); + } + End(offset) => { + debug!("Reached end of module"); + if self.end_reached { + return Err(ParseError::DuplicateSection("End section".into())); + } + + validator.end(offset)?; + self.end_reached = true; + } + UnknownSection { .. } | _ => { + return Err(ParseError::UnsupportedSection(format!("Unknown section"))) + } + }; + + Ok(()) + } +} + +/// A WebAssembly code section +/// Can be cloned to read functions multiple times +#[derive(Debug, Clone)] +pub struct CodeSection<'a> { + pub(crate) functions: Vec>, +} + +impl<'a> CodeSection<'a> { + fn new() -> Self { + Self { + functions: Vec::new(), + } + } +} -- cgit v1.3.1