diff options
Diffstat (limited to 'crates/parser/src/lib.rs')
| -rw-r--r-- | crates/parser/src/lib.rs | 92 |
1 files changed, 72 insertions, 20 deletions
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index d2b6d9c..5b17fb8 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -9,49 +9,101 @@ extern crate std; mod conversion; mod error; mod module; +use alloc::vec::Vec; pub use error::*; use module::ModuleReader; -use tinywasm_types::TinyWasmModule; +use tinywasm_types::{Function, TinyWasmModule}; +use wasmparser::Validator; pub struct Parser {} impl Parser { pub fn parse_module_bytes(wasm: &[u8]) -> Result<TinyWasmModule> { - let reader = ModuleReader::new(); - reader.try_into() - } + let mut validator = Validator::new(); + let mut reader = ModuleReader::new(); + + for payload in wasmparser::Parser::new(0).parse_all(wasm) { + reader.process_payload(payload?, &mut validator)?; + } + + if !reader.end_reached { + return Err(ParseError::EndNotReached); + } - pub fn parse_module_file(file_name: &str) -> Result<TinyWasmModule> { - let reader = ModuleReader::new(); reader.try_into() } #[cfg(feature = "std")] - pub fn parse_module_stream(stream: impl std::io::Read) -> Result<TinyWasmModule> { - let reader = ModuleReader::new(); - reader.try_into() - } + pub fn parse_module_file(path: impl AsRef<crate::std::path::Path>) -> Result<TinyWasmModule> { + use alloc::format; + let f = crate::std::fs::File::open("log.txt").map_err(|e| { + ParseError::Other(format!("Error opening file {:?}: {}", path.as_ref(), e)) + })?; - pub fn read_module_bytes(bytes: &[u8]) -> Result<TinyWasmModule> { - unimplemented!() - } - pub fn read_module_file(file_name: &str) -> Result<TinyWasmModule> { - unimplemented!() + let mut reader = crate::std::io::BufReader::new(f); + Self::parse_module_stream(&mut reader) } + #[cfg(feature = "std")] - pub fn read_module_stream(stream: impl std::io::Read) -> Result<TinyWasmModule> { - unimplemented!() + pub fn parse_module_stream(mut stream: impl std::io::Read) -> Result<TinyWasmModule> { + use alloc::format; + + let mut validator = Validator::new(); + let mut reader = ModuleReader::new(); + let mut buffer = Vec::new(); + let mut parser = wasmparser::Parser::new(0); + let mut eof = false; + + loop { + match parser.parse(&buffer, eof)? { + wasmparser::Chunk::NeedMoreData(hint) => { + let len = buffer.len(); + buffer.extend((0..hint).map(|_| 0u8)); + let read_bytes = stream.read(&mut buffer[len..]).map_err(|e| { + ParseError::Other(format!("Error reading from stream: {}", e)) + })?; + buffer.truncate(len + read_bytes); + eof = read_bytes == 0; + } + wasmparser::Chunk::Parsed { consumed, payload } => { + reader.process_payload(payload, &mut validator)?; + buffer.drain(..consumed); + if eof || reader.end_reached { + return reader.try_into(); + } + } + }; + } } } -impl TryFrom<ModuleReader<'_>> for TinyWasmModule { +impl TryFrom<ModuleReader> for TinyWasmModule { type Error = ParseError; - fn try_from(reader: ModuleReader<'_>) -> Result<Self> { + fn try_from(reader: ModuleReader) -> Result<Self> { if !reader.end_reached { return Err(ParseError::EndNotReached); } - unimplemented!() + let func_types = reader.function_section; + let funcs = reader + .code_section + .into_iter() + .zip(func_types) + .map(|(f, ty)| Function { + body: f.body, + locals: f.locals, + ty, + }) + .collect::<Vec<_>>() + .into_boxed_slice(); + + Ok(TinyWasmModule { + version: reader.version, + start_func: reader.start_func, + types: reader.type_section.into_boxed_slice(), + funcs, + exports: reader.export_section.into_boxed_slice(), + }) } } |
