summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock358
-rw-r--r--Cargo.toml8
-rw-r--r--crates/cli/Cargo.toml15
-rw-r--r--crates/cli/bin.rs43
-rw-r--r--crates/core/Cargo.toml17
-rw-r--r--crates/core/src/bin.rs9
-rw-r--r--crates/core/src/error.rs28
-rw-r--r--crates/core/src/lib.rs185
-rw-r--r--crates/core/src/module.rs155
-rw-r--r--crates/core/src/std.rs18
-rw-r--r--examples/wasm/helloworld.wasm (renamed from crates/core/helloworld.wasm)bin115 -> 115 bytes
-rw-r--r--examples/wasm/helloworld.wat (renamed from crates/core/helloworld.wat)0
12 files changed, 624 insertions, 212 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4a3e0e4..0202089 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,46 +3,360 @@
version = 3
[[package]]
-name = "equivalent"
-version = "1.0.1"
+name = "addr2line"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
[[package]]
-name = "hashbrown"
-version = "0.14.2"
+name = "adler"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
-name = "indexmap"
-version = "2.1.0"
+name = "argh"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219"
dependencies = [
- "equivalent",
- "hashbrown",
+ "argh_derive",
+ "argh_shared",
]
[[package]]
-name = "semver"
-version = "1.0.20"
+name = "argh_derive"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
+checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a"
+dependencies = [
+ "argh_shared",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
-name = "wasmcore"
-version = "0.1.0"
+name = "argh_shared"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "color-eyre"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
+dependencies = [
+ "backtrace",
+ "color-spantrace",
+ "eyre",
+ "indenter",
+ "once_cell",
+ "owo-colors",
+ "tracing-error",
+]
+
+[[package]]
+name = "color-spantrace"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
+dependencies = [
+ "once_cell",
+ "owo-colors",
+ "tracing-core",
+ "tracing-error",
+]
+
+[[package]]
+name = "eyre"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd"
+dependencies = [
+ "indenter",
+ "once_cell",
+]
+
+[[package]]
+name = "gimli"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+
+[[package]]
+name = "indenter"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
+[[package]]
+name = "indexmap-nostd"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.150"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
+
+[[package]]
+name = "memchr"
+version = "2.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "object"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
+[[package]]
+name = "serde"
+version = "1.0.193"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.193"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
- "wasmparser",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "wasmparser"
-version = "0.118.0"
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.39"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror-core"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c001ee18b7e5e3f62cbf58c7fe220119e68d902bb7443179c0c8aef30090e999"
+dependencies = [
+ "thiserror-core-impl",
+]
+
+[[package]]
+name = "thiserror-core-impl"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4c60d69f36615a077cc7663b9cb8e42275722d23e58a7fa3d2c7f2915d09d04"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "tinywasm"
+version = "0.0.0"
+dependencies = [
+ "thiserror-core",
+ "tracing",
+ "wasmparser-nostd",
+]
+
+[[package]]
+name = "tinywasm-cli"
+version = "0.0.0"
+dependencies = [
+ "argh",
+ "color-eyre",
+ "tinywasm",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-error"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
+dependencies = [
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+dependencies = [
+ "sharded-slab",
+ "thread_local",
+ "tracing-core",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
+name = "wasmparser-nostd"
+version = "0.100.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebbb91574de0011ded32b14db12777e7dd5e9ea2f9d7317a1ab51a9495c75924"
+checksum = "9157cab83003221bfd385833ab587a039f5d6fa7304854042ba358a3b09e0724"
dependencies = [
- "indexmap",
- "semver",
+ "indexmap-nostd",
]
diff --git a/Cargo.toml b/Cargo.toml
index 0cfbbe1..42abe2e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,4 @@
[workspace]
-members = [
- "crates/core",
-]
-
-resolver = "2" \ No newline at end of file
+members=["crates/core", "crates/cli"]
+resolver="2"
+default-members=["crates/cli"]
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
new file mode 100644
index 0000000..cdd0266
--- /dev/null
+++ b/crates/cli/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name="tinywasm-cli"
+version="0.0.0"
+edition="2021"
+
+[[bin]]
+name="tinywasm"
+path="bin.rs"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+tinywasm={path="../core"}
+argh="0.1"
+color-eyre="0.6"
diff --git a/crates/cli/bin.rs b/crates/cli/bin.rs
new file mode 100644
index 0000000..4e85481
--- /dev/null
+++ b/crates/cli/bin.rs
@@ -0,0 +1,43 @@
+use argh::FromArgs;
+use color_eyre::eyre::Result;
+use tinywasm::{self, Module};
+
+#[derive(FromArgs)]
+/// TinyWasm CLI
+struct TinyWasmCli {
+ #[argh(subcommand)]
+ nested: TinyWasmSubcommand,
+}
+
+#[derive(FromArgs)]
+#[argh(subcommand)]
+enum TinyWasmSubcommand {
+ Run(Run),
+}
+
+#[derive(FromArgs)]
+/// run a wasm file
+#[argh(subcommand, name = "run")]
+struct Run {
+ /// wasm file to run
+ #[argh(positional)]
+ wasm_file: String,
+}
+
+fn main() -> Result<()> {
+ let args: TinyWasmCli = argh::from_env();
+
+ match args.nested {
+ TinyWasmSubcommand::Run(Run { wasm_file }) => {
+ let wasm = std::fs::read(wasm_file).unwrap();
+ run(&wasm)?;
+ Ok(())
+ }
+ }
+}
+
+fn run(wasm: &[u8]) -> Result<()> {
+ let module = Module::new(wasm)?;
+ println!("{:#?}", module);
+ Ok(())
+}
diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml
index e8c52b9..2f71aa9 100644
--- a/crates/core/Cargo.toml
+++ b/crates/core/Cargo.toml
@@ -1,21 +1,16 @@
[package]
-name="wasmcore"
-version="0.1.0"
+name="tinywasm"
+version="0.0.0"
edition="2021"
[lib]
-name="wasmcore"
path="src/lib.rs"
-[[bin]]
-name="wasmcore"
-path="src/bin.rs"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
[dependencies]
-wasmparser={version="0.118.0", default-features=false}
+thiserror={version="1.0", package="thiserror-core", default-features=false}
+wasmparser={version="0.100", package="wasmparser-nostd", default-features=false}
+tracing={version="0.1.38", default-features=false} # logging
[features]
default=["std"]
-std=[]
+std=["thiserror/std"]
diff --git a/crates/core/src/bin.rs b/crates/core/src/bin.rs
deleted file mode 100644
index c4257e8..0000000
--- a/crates/core/src/bin.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use wasmcore::{self, Module};
-
-pub static WASM: &'static [u8] = include_bytes!("../helloworld.wasm");
-
-fn main() {
- let module = Module::new(WASM);
-
- println!("{:#?}", module);
-}
diff --git a/crates/core/src/error.rs b/crates/core/src/error.rs
new file mode 100644
index 0000000..b9c93c4
--- /dev/null
+++ b/crates/core/src/error.rs
@@ -0,0 +1,28 @@
+use alloc::string::{String, ToString};
+use thiserror::Error;
+
+#[derive(Debug, Error)]
+pub enum Error {
+ #[error("error parsing module")]
+ ParseError { message: String, offset: usize },
+
+ #[error("unknown error: {0}")]
+ Other(String),
+}
+
+impl Error {
+ pub fn other<T>(message: &str) -> Result<T, Self> {
+ Err(Self::Other(message.to_string()))
+ }
+}
+
+impl From<wasmparser::BinaryReaderError> for Error {
+ fn from(value: wasmparser::BinaryReaderError) -> Self {
+ Self::ParseError {
+ message: value.message().to_string(),
+ offset: value.offset(),
+ }
+ }
+}
+
+pub type Result<T, E = Error> = crate::std::result::Result<T, E>;
diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs
index ee8a3be..3d572a2 100644
--- a/crates/core/src/lib.rs
+++ b/crates/core/src/lib.rs
@@ -1,178 +1,33 @@
#![no_std]
#![forbid(unsafe_code)]
+#![cfg_attr(not(feature = "std"), feature(error_in_core))]
-#[cfg(feature = "std")]
-extern crate std;
-use std::println;
-
+mod std;
extern crate alloc;
-use alloc::vec::Vec;
-
-use wasmparser::{
- DataSectionReader, ElementSectionReader, ExportSectionReader, FunctionBody,
- FunctionSectionReader, GlobalSectionReader, ImportSectionReader, MemorySectionReader, Payload,
- TableSectionReader, TypeSectionReader, Validator,
-};
-mod instructions;
-
-struct Store {}
-
-pub struct Module<'a> {
- reader: ModuleReader<'a>,
-}
-
-impl<'a> core::fmt::Debug for Module<'a> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- f.debug_struct("Module")
- .field("version", &self.reader.version)
- .field("type_section", &self.reader.type_section)
- .field("function_section", &self.reader.function_section)
- .field("table_section", &self.reader.table_section)
- .field("memory_section", &self.reader.memory_section)
- .field("global_section", &self.reader.global_section)
- .field("element_section", &self.reader.element_section)
- .field("data_section", &self.reader.data_section)
- .field("code_section", &self.reader.code_section)
- .field("import_section", &self.reader.import_section)
- .field("export_section", &self.reader.export_section)
- .finish()
- }
-}
-
-#[derive(Default)]
-pub struct ModuleReader<'a> {
- pub version: Option<u16>,
- pub type_section: Option<TypeSectionReader<'a>>,
- pub function_section: Option<FunctionSectionReader<'a>>,
- pub table_section: Option<TableSectionReader<'a>>,
- pub memory_section: Option<MemorySectionReader<'a>>,
- pub global_section: Option<GlobalSectionReader<'a>>,
- pub element_section: Option<ElementSectionReader<'a>>,
- pub data_section: Option<DataSectionReader<'a>>,
- pub code_section: Option<CodeSection<'a>>,
- pub import_section: Option<ImportSectionReader<'a>>,
- pub export_section: Option<ExportSectionReader<'a>>,
-}
-
-#[derive(Debug)]
-pub struct CodeSection<'a> {
- pub(crate) functions: Vec<FunctionBody<'a>>,
-}
-impl<'a> CodeSection<'a> {
- fn new() -> Self {
- Self {
- functions: Vec::new(),
- }
- }
-}
-
-impl<'a> Module<'a> {
- pub fn new(wasm: &'a [u8]) -> Result<Module, ()> {
- let mut validator = Validator::new();
- let mut reader = ModuleReader::new();
-
- for payload in wasmparser::Parser::new(0).parse_all(wasm) {
- reader.process_payload(payload.unwrap(), &mut validator)?;
- }
-
- Ok(Self { reader })
- }
-}
-
-impl<'a> ModuleReader<'a> {
- pub fn new() -> Self {
- Self::default()
- }
+mod error;
+pub mod instructions;
+pub mod module;
+pub use error::*;
+pub use module::Module;
- pub fn process_payload(
- &mut self,
- payload: Payload<'a>,
- validator: &mut Validator,
- ) -> Result<bool, ()> {
- use wasmparser::Payload::*;
- match payload {
- Version {
- num,
- encoding,
- range,
- } => {
- validator.version(num, encoding, &range).map_err(|_| ())?;
- self.version = Some(num);
- match encoding {
- wasmparser::Encoding::Module => {}
- wasmparser::Encoding::Component => return Err(()),
- }
- }
- TypeSection(reader) => {
- validator.type_section(&reader).map_err(|_| ())?;
- self.type_section = Some(reader);
- }
- FunctionSection(reader) => {
- validator.function_section(&reader).map_err(|_| ())?;
- self.function_section = Some(reader);
- }
- TableSection(reader) => {
- validator.table_section(&reader).map_err(|_| ())?;
- self.table_section = Some(reader);
- }
- MemorySection(reader) => {
- validator.memory_section(&reader).map_err(|_| ())?;
- self.memory_section = Some(reader);
- }
- GlobalSection(reader) => {
- validator.global_section(&reader).map_err(|_| ())?;
- self.global_section = Some(reader);
- }
- ElementSection(reader) => {
- validator.element_section(&reader).map_err(|_| ())?;
- self.element_section = Some(reader);
- }
- DataSection(reader) => {
- validator.data_section(&reader).map_err(|_| ())?;
- self.data_section = Some(reader);
- }
- CodeSectionStart { count, range, .. } => {
- validator
- .code_section_start(count, &range)
- .map_err(|_| ())?;
+pub struct Store {}
- self.code_section = Some(CodeSection::new());
- }
- CodeSectionEntry(function) => {
- validator.code_section_entry(&function).map_err(|_| ())?;
+pub struct Instance {}
- if let Some(code_section) = &mut self.code_section {
- code_section.functions.push(function);
- } else {
- return Err(());
- }
- }
- ImportSection(reader) => {
- validator.import_section(&reader).map_err(|_| ())?;
- self.import_section = Some(reader);
- }
- ExportSection(reader) => {
- validator.export_section(&reader).map_err(|_| ())?;
- self.export_section = Some(reader);
- }
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{error::Result, Module};
+ use std::dbg;
- End(offset) => {
- validator.end(offset).map_err(|_| ())?;
- return Ok(true);
- }
- x => println!("Unknown payload: {:?}", x),
- };
+ #[test]
+ fn it_works() -> Result<()> {
+ let wasm = include_bytes!("../../../examples/wasm/helloworld.wasm");
+ let module = Module::new(wasm)?;
- Ok(false)
- }
-}
-struct Instance {}
+ dbg!(module);
-pub fn parse(wasm: &[u8]) -> Result<Payload<'_>, ()> {
- for payload in wasmparser::Parser::new(0).parse_all(wasm) {
- return Ok(payload.unwrap());
+ Ok(())
}
-
- return Err(());
}
diff --git a/crates/core/src/module.rs b/crates/core/src/module.rs
new file mode 100644
index 0000000..1ed42c4
--- /dev/null
+++ b/crates/core/src/module.rs
@@ -0,0 +1,155 @@
+use crate::error::{Error, Result};
+use alloc::{format, vec::Vec};
+use tracing::error;
+use wasmparser::*;
+
+pub struct Module<'a> {
+ reader: ModuleReader<'a>,
+}
+
+impl<'a> core::fmt::Debug for Module<'a> {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ f.debug_struct("Module")
+ .field("version", &self.reader.version)
+ .field("type_section", &self.reader.type_section)
+ .field("function_section", &self.reader.function_section)
+ .field("table_section", &self.reader.table_section)
+ .field("memory_section", &self.reader.memory_section)
+ .field("global_section", &self.reader.global_section)
+ .field("element_section", &self.reader.element_section)
+ .field("data_section", &self.reader.data_section)
+ .field("code_section", &self.reader.code_section)
+ .field("import_section", &self.reader.import_section)
+ .field("export_section", &self.reader.export_section)
+ .finish()
+ }
+}
+
+#[derive(Default)]
+pub struct ModuleReader<'a> {
+ pub version: Option<u16>,
+ pub type_section: Option<TypeSectionReader<'a>>,
+ pub function_section: Option<FunctionSectionReader<'a>>,
+ pub table_section: Option<TableSectionReader<'a>>,
+ pub memory_section: Option<MemorySectionReader<'a>>,
+ pub global_section: Option<GlobalSectionReader<'a>>,
+ pub element_section: Option<ElementSectionReader<'a>>,
+ pub data_section: Option<DataSectionReader<'a>>,
+ pub code_section: Option<CodeSection<'a>>,
+ pub import_section: Option<ImportSectionReader<'a>>,
+ pub export_section: Option<ExportSectionReader<'a>>,
+}
+
+#[derive(Debug)]
+pub struct CodeSection<'a> {
+ pub(crate) functions: Vec<FunctionBody<'a>>,
+}
+
+impl<'a> CodeSection<'a> {
+ fn new() -> Self {
+ Self {
+ functions: Vec::new(),
+ }
+ }
+}
+
+impl<'a> Module<'a> {
+ pub fn new(wasm: &'a [u8]) -> Result<Self> {
+ 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)?;
+ }
+
+ Ok(Self { reader })
+ }
+}
+
+impl<'a> ModuleReader<'a> {
+ pub fn new() -> Self {
+ 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 Error::other("Component"),
+ }
+ }
+ TypeSection(reader) => {
+ validator.type_section(&reader)?;
+ self.type_section = Some(reader);
+ }
+ FunctionSection(reader) => {
+ validator.function_section(&reader)?;
+ self.function_section = Some(reader);
+ }
+ TableSection(reader) => {
+ validator.table_section(&reader)?;
+ self.table_section = Some(reader);
+ }
+ MemorySection(reader) => {
+ validator.memory_section(&reader)?;
+ self.memory_section = Some(reader);
+ }
+ GlobalSection(reader) => {
+ validator.global_section(&reader)?;
+ self.global_section = Some(reader);
+ }
+ ElementSection(reader) => {
+ validator.element_section(&reader)?;
+ self.element_section = Some(reader);
+ }
+ DataSection(reader) => {
+ validator.data_section(&reader)?;
+ self.data_section = Some(reader);
+ }
+ CodeSectionStart { count, range, .. } => {
+ validator.code_section_start(count, &range)?;
+
+ self.code_section = Some(CodeSection::new());
+ }
+ CodeSectionEntry(function) => {
+ validator.code_section_entry(&function)?;
+
+ if let Some(code_section) = &mut self.code_section {
+ code_section.functions.push(function);
+ } else {
+ return Error::other("Empty code section");
+ }
+ }
+ ImportSection(reader) => {
+ validator.import_section(&reader)?;
+ self.import_section = Some(reader);
+ }
+ ExportSection(reader) => {
+ validator.export_section(&reader)?;
+ self.export_section = Some(reader);
+ }
+
+ End(offset) => {
+ validator.end(offset)?;
+ return Ok(());
+ }
+ x => Error::other(&format!("Unknown payload: {:?}", x))?,
+ };
+
+ error!("Missing end");
+
+ Ok(())
+ }
+}
diff --git a/crates/core/src/std.rs b/crates/core/src/std.rs
new file mode 100644
index 0000000..6c112f1
--- /dev/null
+++ b/crates/core/src/std.rs
@@ -0,0 +1,18 @@
+pub use core::*;
+
+#[cfg(feature = "std")]
+extern crate std;
+
+#[cfg(feature = "std")]
+pub use std::*;
+
+pub mod error {
+ #[cfg(feature = "std")]
+ extern crate std;
+
+ #[cfg(feature = "std")]
+ pub use std::error::Error;
+
+ #[cfg(not(feature = "std"))]
+ pub use core::error::Error;
+}
diff --git a/crates/core/helloworld.wasm b/examples/wasm/helloworld.wasm
index a5c95d0..a5c95d0 100644
--- a/crates/core/helloworld.wasm
+++ b/examples/wasm/helloworld.wasm
Binary files differ
diff --git a/crates/core/helloworld.wat b/examples/wasm/helloworld.wat
index b74c98f..b74c98f 100644
--- a/crates/core/helloworld.wat
+++ b/examples/wasm/helloworld.wat