From b53b65565721a313ec54122c8b2f0bca00d517ad Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 24 Jul 2023 08:08:51 -0700 Subject: [PATCH] Fix the `Parser::parse` example to work with nested components Fix the `Parser::parse` example to properly push and pop parsers for parsing nested components and modules. While here, also add an example for `Parser::parse_all`, and a top-level wasmparser comment pointing at `Parser::parse` and `Parser::parse_all` as the place to get started with the library. --- crates/wasmparser/src/lib.rs | 3 ++ crates/wasmparser/src/parser.rs | 87 +++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/crates/wasmparser/src/lib.rs b/crates/wasmparser/src/lib.rs index 8f9565c204..bc1516c0eb 100644 --- a/crates/wasmparser/src/lib.rs +++ b/crates/wasmparser/src/lib.rs @@ -22,6 +22,9 @@ //! If you need random access to the entire WebAssembly data-structure, //! this is not the right library for you. You could however, build such //! a data-structure using this library. +//! +//! To get started, create a [`Parser`] using [`Parser::new`] and then follow +//! the examples documented for [`Parser::parse`] or [`Parser::parse_all`]. #![deny(missing_docs)] diff --git a/crates/wasmparser/src/parser.rs b/crates/wasmparser/src/parser.rs index 87c47f2356..0ecfc3b613 100644 --- a/crates/wasmparser/src/parser.rs +++ b/crates/wasmparser/src/parser.rs @@ -424,12 +424,12 @@ impl Parser { /// /// fn parse(mut reader: impl Read) -> Result<()> { /// let mut buf = Vec::new(); - /// let mut parser = Parser::new(0); + /// let mut cur = Parser::new(0); /// let mut eof = false; /// let mut stack = Vec::new(); /// /// loop { - /// let (payload, consumed) = match parser.parse(&buf, eof)? { + /// let (payload, consumed) = match cur.parse(&buf, eof)? { /// Chunk::NeedMoreData(hint) => { /// assert!(!eof); // otherwise an error would be returned /// @@ -476,10 +476,8 @@ impl Parser { /// } /// /// // Sections for WebAssembly components - /// ModuleSection { .. } => { /* ... */ } /// InstanceSection(_) => { /* ... */ } /// CoreTypeSection(_) => { /* ... */ } - /// ComponentSection { .. } => { /* ... */ } /// ComponentInstanceSection(_) => { /* ... */ } /// ComponentAliasSection(_) => { /* ... */ } /// ComponentTypeSection(_) => { /* ... */ } @@ -488,6 +486,12 @@ impl Parser { /// ComponentImportSection(_) => { /* ... */ } /// ComponentExportSection(_) => { /* ... */ } /// + /// ModuleSection { parser, .. } + /// | ComponentSection { parser, .. } => { + /// stack.push(cur.clone()); + /// cur = parser.clone(); + /// } + /// /// CustomSection(_) => { /* ... */ } /// /// // most likely you'd return an error here @@ -498,7 +502,7 @@ impl Parser { /// // we're done. /// End(_) => { /// if let Some(parent_parser) = stack.pop() { - /// parser = parent_parser; + /// cur = parent_parser; /// } else { /// break; /// } @@ -804,6 +808,79 @@ impl Parser { /// Note that when this function yields sections that provide parsers, /// no further action is required for those sections as payloads from /// those parsers will be automatically returned. + /// + /// # Examples + /// + /// An example of reading a wasm file from a stream (`std::io::Read`) into + /// a buffer and then parsing it. + /// + /// ``` + /// use std::io::Read; + /// use anyhow::Result; + /// use wasmparser::{Parser, Chunk, Payload::*}; + /// + /// fn parse(mut reader: impl Read) -> Result<()> { + /// let mut buf = Vec::new(); + /// reader.read_to_end(&mut buf)?; + /// let parser = Parser::new(0); + /// + /// for payload in parser.parse_all(&buf) { + /// match payload? { + /// // Sections for WebAssembly modules + /// Version { .. } => { /* ... */ } + /// TypeSection(_) => { /* ... */ } + /// ImportSection(_) => { /* ... */ } + /// FunctionSection(_) => { /* ... */ } + /// TableSection(_) => { /* ... */ } + /// MemorySection(_) => { /* ... */ } + /// TagSection(_) => { /* ... */ } + /// GlobalSection(_) => { /* ... */ } + /// ExportSection(_) => { /* ... */ } + /// StartSection { .. } => { /* ... */ } + /// ElementSection(_) => { /* ... */ } + /// DataCountSection { .. } => { /* ... */ } + /// DataSection(_) => { /* ... */ } + /// + /// // Here we know how many functions we'll be receiving as + /// // `CodeSectionEntry`, so we can prepare for that, and + /// // afterwards we can parse and handle each function + /// // individually. + /// CodeSectionStart { .. } => { /* ... */ } + /// CodeSectionEntry(body) => { + /// // here we can iterate over `body` to parse the function + /// // and its locals + /// } + /// + /// // Sections for WebAssembly components + /// ModuleSection { .. } => { /* ... */ } + /// InstanceSection(_) => { /* ... */ } + /// CoreTypeSection(_) => { /* ... */ } + /// ComponentSection { .. } => { /* ... */ } + /// ComponentInstanceSection(_) => { /* ... */ } + /// ComponentAliasSection(_) => { /* ... */ } + /// ComponentTypeSection(_) => { /* ... */ } + /// ComponentCanonicalSection(_) => { /* ... */ } + /// ComponentStartSection { .. } => { /* ... */ } + /// ComponentImportSection(_) => { /* ... */ } + /// ComponentExportSection(_) => { /* ... */ } + /// + /// CustomSection(_) => { /* ... */ } + /// + /// // most likely you'd return an error here + /// UnknownSection { id, .. } => { /* ... */ } + /// + /// // Once we've reached the end of a parser we either resume + /// // at the parent parser or the payload iterator is at its + /// // end and we're done. + /// End(_) => {} + /// } + /// } + /// + /// Ok(()) + /// } + /// + /// # parse(&b"\0asm\x01\0\0\0"[..]).unwrap(); + /// ``` pub fn parse_all(self, mut data: &[u8]) -> impl Iterator> { let mut stack = Vec::new(); let mut cur = self;