Skip to content

Commit

Permalink
Fix the Parser::parse example to work with nested components
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sunfishcode committed Jul 24, 2023
1 parent 188de0f commit b53b655
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 5 deletions.
3 changes: 3 additions & 0 deletions crates/wasmparser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]

Expand Down
87 changes: 82 additions & 5 deletions crates/wasmparser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down Expand Up @@ -476,10 +476,8 @@ impl Parser {
/// }
///
/// // Sections for WebAssembly components
/// ModuleSection { .. } => { /* ... */ }
/// InstanceSection(_) => { /* ... */ }
/// CoreTypeSection(_) => { /* ... */ }
/// ComponentSection { .. } => { /* ... */ }
/// ComponentInstanceSection(_) => { /* ... */ }
/// ComponentAliasSection(_) => { /* ... */ }
/// ComponentTypeSection(_) => { /* ... */ }
Expand All @@ -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
Expand All @@ -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;
/// }
Expand Down Expand Up @@ -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<Item = Result<Payload>> {
let mut stack = Vec::new();
let mut cur = self;
Expand Down

0 comments on commit b53b655

Please sign in to comment.