diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7c0b7f386d..04b4542d5a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -152,6 +152,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - run: rustup target add x86_64-unknown-none - run: cargo check --benches -p wasm-smith - run: cargo check --no-default-features - run: cargo check --no-default-features --features print @@ -176,6 +177,9 @@ jobs: - run: cargo check --no-default-features -p wit-parser --features serde - run: cargo check --no-default-features -p wit-parser --features decoding - run: cargo check --no-default-features -p wit-parser --features serde,decoding,wat + - run: cargo check --no-default-features -p wasmparser + - run: cargo check --no-default-features -p wasmparser --target x86_64-unknown-none + - run: cargo check --no-default-features -p wasmparser --features std - run: | if cargo tree -p wasm-smith --no-default-features -e no-dev | grep wasmparser; then echo wasm-smith without default features should not depend on wasmparser diff --git a/Cargo.lock b/Cargo.lock index 07f1238b78..ecb05119ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1803,10 +1803,12 @@ dependencies = [ name = "wasmparser" version = "0.205.0" dependencies = [ + "ahash", "anyhow", "bitflags 2.4.2", "criterion", "env_logger", + "hashbrown 0.14.3", "indexmap 2.2.5", "log", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 76515555fb..321119d3bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ clap = { version = "4.0.0", features = ["derive"] } clap_complete = "4.4.7" criterion = "0.3.3" env_logger = "0.11" -indexmap = "2.0.0" +indexmap = { version = "2.0.0", default-features = false } leb128 = "0.2.4" libfuzzer-sys = "0.4.0" log = "0.4.17" @@ -55,10 +55,12 @@ serde_json = { version = "1" } wasmtime = { version = "20.0.0", default-features = false, features = ['cranelift', 'component-model', 'runtime', 'gc'] } url = "2.0.0" pretty_assertions = "1.3.0" -semver = "1.0.0" +semver = { version = "1.0.0", default-features = false } smallvec = "1.11.1" libtest-mimic = "0.7.0" bitflags = "2.5.0" +hashbrown = { version = "0.14.3", default-features = false, features = ['ahash'] } +ahash = { version = "0.8.11", default-features = false } wasm-compose = { version = "0.205.0", path = "crates/wasm-compose" } wasm-encoder = { version = "0.205.0", path = "crates/wasm-encoder" } diff --git a/crates/wasm-compose/src/encoding.rs b/crates/wasm-compose/src/encoding.rs index bacd9d5111..39dd232f54 100644 --- a/crates/wasm-compose/src/encoding.rs +++ b/crates/wasm-compose/src/encoding.rs @@ -730,7 +730,7 @@ impl<'a> TypeEncoder<'a> { index } - fn flags(encodable: &mut Encodable, names: &IndexSet) -> u32 { + fn flags(encodable: &mut Encodable, names: &wasmparser::map::IndexSet) -> u32 { let index = encodable.type_count(); encodable .ty() @@ -739,7 +739,7 @@ impl<'a> TypeEncoder<'a> { index } - fn enum_type(encodable: &mut Encodable, cases: &IndexSet) -> u32 { + fn enum_type(encodable: &mut Encodable, cases: &wasmparser::map::IndexSet) -> u32 { let index = encodable.type_count(); encodable .ty() diff --git a/crates/wasmparser/Cargo.toml b/crates/wasmparser/Cargo.toml index 69e01c40d6..435ba3d37e 100644 --- a/crates/wasmparser/Cargo.toml +++ b/crates/wasmparser/Cargo.toml @@ -19,6 +19,8 @@ workspace = true bitflags = "2.4.1" indexmap = { workspace = true } semver = { workspace = true } +hashbrown = { workspace = true } +ahash = { workspace = true } [dev-dependencies] anyhow = { workspace = true } @@ -34,3 +36,7 @@ log.workspace = true [[bench]] name = "benchmark" harness = false + +[features] +default = ['std'] +std = ['indexmap/std'] diff --git a/crates/wasmparser/LICENSE b/crates/wasmparser/LICENSE deleted file mode 120000 index 30cff7403d..0000000000 --- a/crates/wasmparser/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE \ No newline at end of file diff --git a/crates/wasmparser/src/binary_reader.rs b/crates/wasmparser/src/binary_reader.rs index 9fde1a02c5..0ed30e3a28 100644 --- a/crates/wasmparser/src/binary_reader.rs +++ b/crates/wasmparser/src/binary_reader.rs @@ -13,12 +13,12 @@ * limitations under the License. */ +use crate::prelude::*; use crate::{limits::*, *}; -use std::error::Error; -use std::fmt; -use std::marker; -use std::ops::Range; -use std::str; +use core::fmt; +use core::marker; +use core::ops::Range; +use core::str; pub(crate) const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm"; @@ -39,9 +39,10 @@ pub(crate) struct BinaryReaderErrorInner { } /// The result for `BinaryReader` operations. -pub type Result = std::result::Result; +pub type Result = core::result::Result; -impl Error for BinaryReaderError {} +#[cfg(feature = "std")] +impl std::error::Error for BinaryReaderError {} impl fmt::Display for BinaryReaderError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/crates/wasmparser/src/lib.rs b/crates/wasmparser/src/lib.rs index d2b6ced8e3..6c728a1ca6 100644 --- a/crates/wasmparser/src/lib.rs +++ b/crates/wasmparser/src/lib.rs @@ -27,6 +27,28 @@ //! the examples documented for [`Parser::parse`] or [`Parser::parse_all`]. #![deny(missing_docs)] +#![no_std] + +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +/// A small "prelude" to use throughout this crate. +/// +/// This crate is tagged with `#![no_std]` meaning that we get libcore's prelude +/// by default. This crate also uses `alloc`, however, and common types there +/// like `String`. This custom prelude helps bring those types into scope to +/// avoid having to import each of them manually. +mod prelude { + pub use alloc::borrow::ToOwned; + pub use alloc::boxed::Box; + pub use alloc::format; + pub use alloc::string::{String, ToString}; + pub use alloc::vec; + pub use alloc::vec::Vec; + + pub use crate::map::{HashMap, HashSet, IndexMap, IndexSet}; +} /// A helper macro to conveniently iterate over all opcodes recognized by this /// crate. This can be used to work with either the [`Operator`] enumeration or @@ -770,3 +792,5 @@ mod parser; mod readers; mod resources; mod validator; + +pub mod map; diff --git a/crates/wasmparser/src/map.rs b/crates/wasmparser/src/map.rs new file mode 100644 index 0000000000..e2e15e2b90 --- /dev/null +++ b/crates/wasmparser/src/map.rs @@ -0,0 +1,126 @@ +//! Type aliases for maps used by `wasmparser` +//! +//! This module contains type aliases used for [`HashMap`], [`HashSet`], +//! [`IndexMap`], and [`IndexSet`]. Note that these differ from upstream types +//! in the `indexmap` crate and the standard library due to customization of the +//! hash algorithm type parameter. + +use core::hash::{BuildHasher, Hasher}; + +/// Wasmparser-specific type alias for an ordered map. +pub type IndexMap = indexmap::IndexMap; + +/// Wasmparser-specific type alias for an ordered set. +pub type IndexSet = indexmap::IndexSet; + +/// Wasmparser-specific type alias for hash map. +pub type HashMap = hashbrown::HashMap; + +/// Wasmparser-specific type alias for hash set. +pub type HashSet = hashbrown::HashSet; + +/// Wasmparser's hashing state stored per-map. +/// +/// This is DoS-resistant when the `std` feature is activated and still somewhat +/// resistant when it's not active but not as secure. +#[derive(Clone, Debug)] +pub struct RandomState(RandomStateImpl); + +impl Default for RandomState { + #[inline] + fn default() -> RandomState { + RandomState(RandomStateImpl::default()) + } +} + +impl BuildHasher for RandomState { + type Hasher = RandomStateHasher; + + #[inline] + fn build_hasher(&self) -> RandomStateHasher { + RandomStateHasher(self.0.build_hasher()) + } +} + +/// Wasmparser's hasher type used with [`RandomState`]. +pub struct RandomStateHasher(::Hasher); + +impl Hasher for RandomStateHasher { + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } + #[inline] + fn write(&mut self, bytes: &[u8]) { + self.0.write(bytes) + } + #[inline] + fn write_u8(&mut self, i: u8) { + self.0.write_u8(i) + } + #[inline] + fn write_u16(&mut self, i: u16) { + self.0.write_u16(i) + } + #[inline] + fn write_u32(&mut self, i: u32) { + self.0.write_u32(i) + } + #[inline] + fn write_u64(&mut self, i: u64) { + self.0.write_u64(i) + } + #[inline] + fn write_u128(&mut self, i: u128) { + self.0.write_u128(i) + } + #[inline] + fn write_usize(&mut self, i: usize) { + self.0.write_usize(i) + } + #[inline] + fn write_i8(&mut self, i: i8) { + self.0.write_i8(i) + } + #[inline] + fn write_i16(&mut self, i: i16) { + self.0.write_i16(i) + } + #[inline] + fn write_i32(&mut self, i: i32) { + self.0.write_i32(i) + } + #[inline] + fn write_i64(&mut self, i: i64) { + self.0.write_i64(i) + } + #[inline] + fn write_i128(&mut self, i: i128) { + self.0.write_i128(i) + } + #[inline] + fn write_isize(&mut self, i: isize) { + self.0.write_isize(i) + } +} + +// When the `std` feature is active reuse the standard library's implementation +// of hash state and hasher. +#[cfg(feature = "std")] +use std::collections::hash_map::RandomState as RandomStateImpl; + +// When the `std` feature is NOT active then rely on `ahash::RandomState`. That +// relies on ASLR by default for randomness. +#[derive(Default, Clone, Debug)] +#[cfg(not(feature = "std"))] +struct RandomStateImpl; + +#[cfg(not(feature = "std"))] +impl BuildHasher for RandomStateImpl { + type Hasher = ahash::AHasher; + + #[inline] + fn build_hasher(&self) -> ahash::AHasher { + ahash::RandomState::new().build_hasher() + } +} diff --git a/crates/wasmparser/src/parser.rs b/crates/wasmparser/src/parser.rs index 8497326d83..75afed4239 100644 --- a/crates/wasmparser/src/parser.rs +++ b/crates/wasmparser/src/parser.rs @@ -1,4 +1,5 @@ use crate::binary_reader::WASM_MAGIC_NUMBER; +use crate::prelude::*; use crate::CoreTypeSectionReader; use crate::{ limits::MAX_WASM_MODULE_SIZE, BinaryReader, BinaryReaderError, ComponentCanonicalSectionReader, @@ -8,9 +9,9 @@ use crate::{ GlobalSectionReader, ImportSectionReader, InstanceSectionReader, MemorySectionReader, Result, SectionLimited, TableSectionReader, TagSectionReader, TypeSectionReader, }; -use std::fmt; -use std::iter; -use std::ops::Range; +use core::fmt; +use core::iter; +use core::ops::Range; pub(crate) const WASM_MODULE_VERSION: u16 = 0x1; @@ -952,7 +953,7 @@ impl Parser { /// /// ``` /// use wasmparser::{Result, Parser, Chunk, Payload::*}; - /// use std::ops::Range; + /// use core::ops::Range; /// /// fn objdump_headers(mut wasm: &[u8]) -> Result<()> { /// let mut parser = Parser::new(0); diff --git a/crates/wasmparser/src/readers.rs b/crates/wasmparser/src/readers.rs index e2b25da7cf..60e1507177 100644 --- a/crates/wasmparser/src/readers.rs +++ b/crates/wasmparser/src/readers.rs @@ -14,9 +14,9 @@ */ use crate::{BinaryReader, BinaryReaderError, Result}; -use std::fmt; -use std::marker; -use std::ops::Range; +use ::core::fmt; +use ::core::marker; +use ::core::ops::Range; mod component; mod core; diff --git a/crates/wasmparser/src/readers/component/canonicals.rs b/crates/wasmparser/src/readers/component/canonicals.rs index 3b8c64b7b9..53bfe9da2b 100644 --- a/crates/wasmparser/src/readers/component/canonicals.rs +++ b/crates/wasmparser/src/readers/component/canonicals.rs @@ -1,4 +1,5 @@ use crate::limits::MAX_WASM_CANONICAL_OPTIONS; +use crate::prelude::*; use crate::{BinaryReader, FromReader, Result, SectionLimited}; /// Represents options for component functions. diff --git a/crates/wasmparser/src/readers/component/instances.rs b/crates/wasmparser/src/readers/component/instances.rs index a33762c420..1c8fcd06b7 100644 --- a/crates/wasmparser/src/readers/component/instances.rs +++ b/crates/wasmparser/src/readers/component/instances.rs @@ -1,4 +1,5 @@ use crate::limits::{MAX_WASM_INSTANTIATION_ARGS, MAX_WASM_INSTANTIATION_EXPORTS}; +use crate::prelude::*; use crate::{ BinaryReader, ComponentExport, ComponentExternalKind, Export, FromReader, Result, SectionLimited, diff --git a/crates/wasmparser/src/readers/component/names.rs b/crates/wasmparser/src/readers/component/names.rs index 19de2752d0..3290642384 100644 --- a/crates/wasmparser/src/readers/component/names.rs +++ b/crates/wasmparser/src/readers/component/names.rs @@ -1,5 +1,5 @@ use crate::{BinaryReader, BinaryReaderError, NameMap, Result, Subsection, Subsections}; -use std::ops::Range; +use core::ops::Range; /// Type used to iterate and parse the contents of the `component-name` custom /// section in compnents, similar to the `name` section of core modules. diff --git a/crates/wasmparser/src/readers/component/start.rs b/crates/wasmparser/src/readers/component/start.rs index dc01fa4340..f2cb9225d4 100644 --- a/crates/wasmparser/src/readers/component/start.rs +++ b/crates/wasmparser/src/readers/component/start.rs @@ -1,4 +1,5 @@ use crate::limits::{MAX_WASM_FUNCTION_RETURNS, MAX_WASM_START_ARGS}; +use crate::prelude::*; use crate::{BinaryReader, FromReader, Result}; /// Represents the start function in a WebAssembly component. diff --git a/crates/wasmparser/src/readers/component/types.rs b/crates/wasmparser/src/readers/component/types.rs index 6e589f5a5a..7b36775809 100644 --- a/crates/wasmparser/src/readers/component/types.rs +++ b/crates/wasmparser/src/readers/component/types.rs @@ -1,9 +1,10 @@ use crate::limits::*; +use crate::prelude::*; use crate::{ BinaryReader, ComponentAlias, ComponentExportName, ComponentImport, ComponentTypeRef, FromReader, Import, Result, SectionLimited, SubType, TypeRef, ValType, }; -use std::fmt; +use core::fmt; /// Represents the kind of an outer core alias in a WebAssembly component. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -420,7 +421,7 @@ impl ComponentFuncResult<'_> { } match self { - Self::Unnamed(ty) => Either::Left(std::iter::once(ty).map(|ty| (None, ty))), + Self::Unnamed(ty) => Either::Left(core::iter::once(ty).map(|ty| (None, ty))), Self::Named(vec) => Either::Right(vec.iter().map(|(n, ty)| (Some(*n), ty))), } } diff --git a/crates/wasmparser/src/readers/core/code.rs b/crates/wasmparser/src/readers/core/code.rs index 2a463727e8..dab9e2f2cd 100644 --- a/crates/wasmparser/src/readers/core/code.rs +++ b/crates/wasmparser/src/readers/core/code.rs @@ -14,7 +14,7 @@ */ use crate::{BinaryReader, FromReader, OperatorsReader, Result, SectionLimited, ValType}; -use std::ops::Range; +use core::ops::Range; /// A reader for the code section of a WebAssembly module. pub type CodeSectionReader<'a> = SectionLimited<'a, FunctionBody<'a>>; diff --git a/crates/wasmparser/src/readers/core/coredumps.rs b/crates/wasmparser/src/readers/core/coredumps.rs index 3579fdcefe..8fd2985953 100644 --- a/crates/wasmparser/src/readers/core/coredumps.rs +++ b/crates/wasmparser/src/readers/core/coredumps.rs @@ -1,3 +1,4 @@ +use crate::prelude::*; use crate::{BinaryReader, FromReader, Result}; /// The data portion of a custom section representing a core dump. Per the diff --git a/crates/wasmparser/src/readers/core/custom.rs b/crates/wasmparser/src/readers/core/custom.rs index a04fe5a1ac..71ec8087b4 100644 --- a/crates/wasmparser/src/readers/core/custom.rs +++ b/crates/wasmparser/src/readers/core/custom.rs @@ -1,5 +1,6 @@ use crate::{BinaryReader, Result}; -use std::ops::Range; +use core::fmt; +use core::ops::Range; /// A reader for custom sections of a WebAssembly module. #[derive(Clone)] @@ -51,8 +52,8 @@ impl<'a> CustomSectionReader<'a> { } } -impl<'a> std::fmt::Debug for CustomSectionReader<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl<'a> fmt::Debug for CustomSectionReader<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("CustomSectionReader") .field("name", &self.name) .field("data_offset", &self.data_offset) diff --git a/crates/wasmparser/src/readers/core/data.rs b/crates/wasmparser/src/readers/core/data.rs index 5ea5f99457..f752c6e0a3 100644 --- a/crates/wasmparser/src/readers/core/data.rs +++ b/crates/wasmparser/src/readers/core/data.rs @@ -14,7 +14,7 @@ */ use crate::{BinaryReader, BinaryReaderError, ConstExpr, FromReader, Result, SectionLimited}; -use std::ops::Range; +use core::ops::Range; /// Represents a data segment in a core WebAssembly module. #[derive(Debug, Clone)] diff --git a/crates/wasmparser/src/readers/core/dylink0.rs b/crates/wasmparser/src/readers/core/dylink0.rs index 671022ea01..7e92fac882 100644 --- a/crates/wasmparser/src/readers/core/dylink0.rs +++ b/crates/wasmparser/src/readers/core/dylink0.rs @@ -1,5 +1,6 @@ +use crate::prelude::*; use crate::{BinaryReader, Result, Subsection, Subsections, SymbolFlags}; -use std::ops::Range; +use core::ops::Range; /// Parser for the dynamic linking `dylink.0` custom section. /// diff --git a/crates/wasmparser/src/readers/core/elements.rs b/crates/wasmparser/src/readers/core/elements.rs index a8bbb17d52..3e5b6c6135 100644 --- a/crates/wasmparser/src/readers/core/elements.rs +++ b/crates/wasmparser/src/readers/core/elements.rs @@ -17,7 +17,7 @@ use crate::{ BinaryReader, BinaryReaderError, ConstExpr, ExternalKind, FromReader, RefType, Result, SectionLimited, }; -use std::ops::Range; +use core::ops::Range; /// Represents a core WebAssembly element segment. #[derive(Clone)] diff --git a/crates/wasmparser/src/readers/core/linking.rs b/crates/wasmparser/src/readers/core/linking.rs index f70611e98e..b0601e7f8d 100644 --- a/crates/wasmparser/src/readers/core/linking.rs +++ b/crates/wasmparser/src/readers/core/linking.rs @@ -1,7 +1,8 @@ +use crate::prelude::*; use crate::{ BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections, }; -use std::ops::Range; +use core::ops::Range; bitflags::bitflags! { /// Flags for WebAssembly symbols. diff --git a/crates/wasmparser/src/readers/core/names.rs b/crates/wasmparser/src/readers/core/names.rs index 93633854f6..d5278b8efb 100644 --- a/crates/wasmparser/src/readers/core/names.rs +++ b/crates/wasmparser/src/readers/core/names.rs @@ -16,7 +16,7 @@ use crate::{ BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections, }; -use std::ops::Range; +use core::ops::Range; /// Represents a name map from the names custom section. pub type NameMap<'a> = SectionLimited<'a, Naming<'a>>; diff --git a/crates/wasmparser/src/readers/core/operators.rs b/crates/wasmparser/src/readers/core/operators.rs index 7b5b38543f..2dfd4b0c19 100644 --- a/crates/wasmparser/src/readers/core/operators.rs +++ b/crates/wasmparser/src/readers/core/operators.rs @@ -14,6 +14,7 @@ */ use crate::limits::MAX_WASM_CATCHES; +use crate::prelude::*; use crate::{BinaryReader, BinaryReaderError, FromReader, Result, ValType}; /// Represents a block type. diff --git a/crates/wasmparser/src/readers/core/reloc.rs b/crates/wasmparser/src/readers/core/reloc.rs index f1c8aa4260..2b0ad73c7f 100644 --- a/crates/wasmparser/src/readers/core/reloc.rs +++ b/crates/wasmparser/src/readers/core/reloc.rs @@ -1,6 +1,5 @@ -use std::ops::Range; - use crate::{BinaryReader, FromReader, Result, SectionLimited}; +use core::ops::Range; /// Reader for relocation entries within a `reloc.*` section. pub type RelocationEntryReader<'a> = SectionLimited<'a, RelocationEntry>; @@ -53,7 +52,7 @@ macro_rules! back_to_enum { $($(#[$vmeta])* $vname $(= $val)?,)* } - impl std::convert::TryFrom for $name { + impl TryFrom for $name { type Error = (); fn try_from(v: u8) -> Result { diff --git a/crates/wasmparser/src/readers/core/types.rs b/crates/wasmparser/src/readers/core/types.rs index 20f06fe2f4..dd313c3e13 100644 --- a/crates/wasmparser/src/readers/core/types.rs +++ b/crates/wasmparser/src/readers/core/types.rs @@ -17,10 +17,11 @@ use crate::limits::{ MAX_WASM_FUNCTION_PARAMS, MAX_WASM_FUNCTION_RETURNS, MAX_WASM_STRUCT_FIELDS, MAX_WASM_SUPERTYPES, MAX_WASM_TYPES, }; +use crate::prelude::*; use crate::types::CoreTypeId; use crate::{BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited}; -use std::fmt::{self, Debug, Write}; -use std::hash::{Hash, Hasher}; +use core::fmt::{self, Debug, Write}; +use core::hash::{Hash, Hasher}; mod matches; pub(crate) use self::matches::{Matches, WithRecGroup}; @@ -201,8 +202,8 @@ impl PackedIndex { } } -impl std::fmt::Debug for PackedIndex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Debug for PackedIndex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("CoreTypeIndex") .field( "kind", @@ -218,9 +219,9 @@ impl std::fmt::Debug for PackedIndex { } } -impl std::fmt::Display for PackedIndex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(&self.unpack(), f) +impl fmt::Display for PackedIndex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result { + fmt::Display::fmt(&self.unpack(), f) } } @@ -288,8 +289,8 @@ impl UnpackedIndex { } } -impl std::fmt::Display for UnpackedIndex { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for UnpackedIndex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result { match self { UnpackedIndex::Module(i) => write!(f, "(module {i})"), UnpackedIndex::RecGroup(i) => write!(f, "(recgroup {i})"), @@ -334,7 +335,7 @@ impl RecGroup { /// Returns the list of subtypes in the recursive type group. pub fn types(&self) -> impl ExactSizeIterator + '_ { let types = match &self.inner { - RecGroupInner::Implicit(ty) => std::slice::from_ref(ty), + RecGroupInner::Implicit(ty) => core::slice::from_ref(ty), RecGroupInner::Explicit(types) => types, }; types.iter().map(|(_, ty)| ty) @@ -344,7 +345,7 @@ impl RecGroup { /// recursive type group. pub(crate) fn types_mut(&mut self) -> impl ExactSizeIterator + '_ { let types = match &mut self.inner { - RecGroupInner::Implicit(ty) => std::slice::from_mut(ty), + RecGroupInner::Implicit(ty) => core::slice::from_mut(ty), RecGroupInner::Explicit(types) => types, }; types.iter_mut().map(|(_, ty)| ty) @@ -366,7 +367,7 @@ impl RecGroup { enum Iter { Implicit(Option<(usize, SubType)>), - Explicit(std::vec::IntoIter<(usize, SubType)>), + Explicit(alloc::vec::IntoIter<(usize, SubType)>), } impl Iterator for Iter { @@ -423,10 +424,10 @@ pub struct SubType { pub composite_type: CompositeType, } -impl std::fmt::Display for SubType { +impl fmt::Display for SubType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_final && self.supertype_idx.is_none() { - std::fmt::Display::fmt(&self.composite_type, f) + fmt::Display::fmt(&self.composite_type, f) } else { write!(f, "(sub ")?; if self.is_final { @@ -435,7 +436,7 @@ impl std::fmt::Display for SubType { if let Some(idx) = self.supertype_idx { write!(f, "{idx} ")?; } - std::fmt::Display::fmt(&self.composite_type, f)?; + fmt::Display::fmt(&self.composite_type, f)?; write!(f, ")") } } @@ -504,7 +505,7 @@ pub enum CompositeType { Struct(StructType), } -impl std::fmt::Display for CompositeType { +impl fmt::Display for CompositeType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Self::Array(_) => write!(f, "(array ...)"), @@ -549,8 +550,8 @@ pub struct FuncType { len_params: usize, } -impl std::fmt::Debug for FuncType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Debug for FuncType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("FuncType") .field("params", &self.params()) .field("results", &self.results()) @@ -671,12 +672,12 @@ pub enum StorageType { Val(ValType), } -impl std::fmt::Display for StorageType { +impl fmt::Display for StorageType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::I8 => write!(f, "i8"), Self::I16 => write!(f, "i16"), - Self::Val(v) => std::fmt::Display::fmt(v, f), + Self::Val(v) => fmt::Display::fmt(v, f), } } } @@ -732,15 +733,15 @@ impl From for ValType { } } -impl std::fmt::Display for ValType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for ValType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ValType::I32 => f.write_str("i32"), ValType::I64 => f.write_str("i64"), ValType::F32 => f.write_str("f32"), ValType::F64 => f.write_str("f64"), ValType::V128 => f.write_str("v128"), - ValType::Ref(r) => std::fmt::Display::fmt(r, f), + ValType::Ref(r) => fmt::Display::fmt(r, f), } } } @@ -862,8 +863,8 @@ impl ValType { #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct RefType([u8; 3]); -impl std::fmt::Debug for RefType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Debug for RefType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match (self.is_nullable(), self.heap_type()) { (true, HeapType::Any) => write!(f, "anyref"), (false, HeapType::Any) => write!(f, "(ref any)"), @@ -895,9 +896,9 @@ impl std::fmt::Debug for RefType { } } -impl std::fmt::Display for RefType { +impl fmt::Display for RefType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - std::fmt::Debug::fmt(self, f) + fmt::Debug::fmt(self, f) } } diff --git a/crates/wasmparser/src/readers/core/types/matches.rs b/crates/wasmparser/src/readers/core/types/matches.rs index 452677c51c..5976b305ac 100644 --- a/crates/wasmparser/src/readers/core/types/matches.rs +++ b/crates/wasmparser/src/readers/core/types/matches.rs @@ -49,7 +49,7 @@ impl WithRecGroup { } } -impl std::ops::Deref for WithRecGroup { +impl core::ops::Deref for WithRecGroup { type Target = T; #[inline] @@ -58,7 +58,7 @@ impl std::ops::Deref for WithRecGroup { } } -impl std::ops::DerefMut for WithRecGroup { +impl core::ops::DerefMut for WithRecGroup { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner diff --git a/crates/wasmparser/src/resources.rs b/crates/wasmparser/src/resources.rs index 8c780c7ee8..20ce74358a 100644 --- a/crates/wasmparser/src/resources.rs +++ b/crates/wasmparser/src/resources.rs @@ -173,7 +173,7 @@ where } } -impl WasmModuleResources for std::sync::Arc +impl WasmModuleResources for alloc::sync::Arc where T: WasmModuleResources, { diff --git a/crates/wasmparser/src/validator.rs b/crates/wasmparser/src/validator.rs index 19f88a9b9e..8fd8bdda40 100644 --- a/crates/wasmparser/src/validator.rs +++ b/crates/wasmparser/src/validator.rs @@ -13,15 +13,16 @@ * limitations under the License. */ +use crate::prelude::*; use crate::{ limits::*, BinaryReaderError, Encoding, FromReader, FunctionBody, HeapType, Parser, Payload, RefType, Result, SectionLimited, ValType, WASM_COMPONENT_VERSION, WASM_MODULE_VERSION, }; +use ::core::mem; +use ::core::ops::Range; +use ::core::sync::atomic::{AtomicUsize, Ordering}; +use alloc::sync::Arc; use bitflags::bitflags; -use std::mem; -use std::ops::Range; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; /// Test whether the given buffer contains a valid WebAssembly module or component, /// analogous to [`WebAssembly.validate`][js] in the JS API. @@ -1465,7 +1466,7 @@ impl Validator { /// /// Returns the types known to the validator for the module or component. pub fn end(&mut self, offset: usize) -> Result { - match std::mem::replace(&mut self.state, State::End) { + match mem::replace(&mut self.state, State::End) { State::Unparsed(_) => Err(BinaryReaderError::new( "cannot call `end` before a header has been parsed", offset, diff --git a/crates/wasmparser/src/validator/component.rs b/crates/wasmparser/src/validator/component.rs index 9e60ef2214..13f13a497a 100644 --- a/crates/wasmparser/src/validator/component.rs +++ b/crates/wasmparser/src/validator/component.rs @@ -10,6 +10,7 @@ use super::{ ModuleType, RecordType, Remapping, ResourceId, TypeAlloc, TypeList, VariantCase, }, }; +use crate::prelude::*; use crate::validator::names::{ComponentName, ComponentNameKind, KebabStr, KebabString}; use crate::{ limits::*, @@ -23,9 +24,8 @@ use crate::{ InstantiationArgKind, MemoryType, RecGroup, Result, SubType, TableType, TypeBounds, ValType, WasmFeatures, }; -use indexmap::{map::Entry, IndexMap, IndexSet}; -use std::collections::{HashMap, HashSet}; -use std::mem; +use core::mem; +use indexmap::map::Entry; fn to_kebab_str<'a>(s: &'a str, desc: &str, offset: usize) -> Result<&'a KebabStr> { match KebabStr::new(s) { @@ -757,7 +757,7 @@ impl ComponentState { // The resource referred to by own/borrow must be named. ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => { - set.contains(&(*id).into()) + set.contains(&ComponentAnyTypeId::from(*id)) } } } @@ -1656,8 +1656,8 @@ impl ComponentState { ) -> Result { let mut info = TypeInfo::new(); - let mut set = - HashSet::with_capacity(std::cmp::max(ty.params.len(), ty.results.type_count())); + let mut set = HashSet::default(); + set.reserve(core::cmp::max(ty.params.len(), ty.results.type_count())); let params = ty .params @@ -1740,7 +1740,7 @@ impl ComponentState { } let module_type_id = self.module_at(module_index, offset)?; - let mut args = IndexMap::new(); + let mut args = IndexMap::default(); // Populate the arguments for module_arg in module_args { @@ -1802,7 +1802,7 @@ impl ComponentState { offset: usize, ) -> Result { let component_type_id = self.component_at(component_index, offset)?; - let mut args = IndexMap::new(); + let mut args = IndexMap::default(); // Populate the arguments for component_arg in component_args { @@ -2025,7 +2025,7 @@ impl ComponentState { // // In debug mode, however, do a sanity check. if cfg!(debug_assertions) { - let mut free = IndexSet::new(); + let mut free = IndexSet::default(); for ty in exports.values() { types.free_variables_component_entity(ty, &mut free); } @@ -2070,9 +2070,9 @@ impl ComponentState { offset: usize, ) -> Result { let mut info = TypeInfo::new(); - let mut inst_exports = IndexMap::new(); - let mut explicit_resources = IndexMap::new(); - let mut export_names = IndexSet::new(); + let mut inst_exports = IndexMap::default(); + let mut explicit_resources = IndexMap::default(); + let mut export_names = IndexSet::default(); // NB: It's intentional that this context is empty since no indices are // introduced in the bag-of-exports construct which means there's no @@ -2209,7 +2209,7 @@ impl ComponentState { } let mut info = TypeInfo::new(); - let mut inst_exports = IndexMap::new(); + let mut inst_exports = IndexMap::default(); for export in exports { match export.kind { ExternalKind::Func => { @@ -2485,7 +2485,7 @@ impl ComponentState { let pos_after_component = components.len() - (count as usize); if let Some(component) = components.get(pos_after_component) { if component.kind == ComponentKind::Component { - let mut free = IndexSet::new(); + let mut free = IndexSet::default(); types.free_variables_any_type_id(ty, &mut free); if !free.is_empty() { bail!( @@ -2567,7 +2567,8 @@ impl ComponentState { offset: usize, ) -> Result { let mut info = TypeInfo::new(); - let mut field_map = IndexMap::with_capacity(fields.len()); + let mut field_map = IndexMap::default(); + field_map.reserve(fields.len()); if fields.is_empty() { bail!(offset, "record type must have at least one field"); @@ -2603,7 +2604,8 @@ impl ComponentState { offset: usize, ) -> Result { let mut info = TypeInfo::new(); - let mut case_map: IndexMap = IndexMap::with_capacity(cases.len()); + let mut case_map: IndexMap = IndexMap::default(); + case_map.reserve(cases.len()); if cases.is_empty() { bail!(offset, "variant type must have at least one case"); @@ -2686,7 +2688,8 @@ impl ComponentState { } fn create_flags_type(&self, names: &[&str], offset: usize) -> Result { - let mut names_set = IndexSet::with_capacity(names.len()); + let mut names_set = IndexSet::default(); + names_set.reserve(names.len()); if names.is_empty() { bail!(offset, "flags must have at least one entry"); @@ -2718,7 +2721,8 @@ impl ComponentState { bail!(offset, "enum type must have at least one variant"); } - let mut tags = IndexSet::with_capacity(cases.len()); + let mut tags = IndexSet::default(); + tags.reserve(cases.len()); for tag in cases { let tag = to_kebab_str(tag, "enum tag", offset)?; @@ -3199,9 +3203,9 @@ impl ComponentNameContext { use self::append_only::*; mod append_only { - use indexmap::IndexMap; - use std::hash::Hash; - use std::ops::Deref; + use crate::prelude::IndexMap; + use core::hash::Hash; + use core::ops::Deref; pub struct IndexMapAppendOnly(IndexMap); diff --git a/crates/wasmparser/src/validator/core.rs b/crates/wasmparser/src/validator/core.rs index 1fb8f83470..99f983e480 100644 --- a/crates/wasmparser/src/validator/core.rs +++ b/crates/wasmparser/src/validator/core.rs @@ -9,6 +9,7 @@ use super::{ operators::{ty_to_str, OperatorValidator, OperatorValidatorAllocations}, types::{CoreTypeId, EntityType, RecGroupId, TypeAlloc, TypeList}, }; +use crate::prelude::*; use crate::{ limits::*, validator::types::TypeIdentifier, BinaryReaderError, CompositeType, ConstExpr, Data, DataKind, Element, ElementKind, ExternalKind, FuncType, Global, GlobalType, HeapType, @@ -16,9 +17,8 @@ use crate::{ TableType, TagType, TypeRef, UnpackedIndex, ValType, VisitOperator, WasmFeatures, WasmModuleResources, }; -use indexmap::IndexMap; -use std::mem; -use std::{collections::HashSet, sync::Arc}; +use alloc::sync::Arc; +use core::mem; // Section order for WebAssembly modules. // @@ -1362,8 +1362,8 @@ const _: () = { }; mod arc { - use std::ops::Deref; - use std::sync::Arc; + use alloc::sync::Arc; + use core::ops::Deref; enum Inner { Owned(T), @@ -1405,7 +1405,7 @@ mod arc { return; } - let inner = std::mem::replace(&mut self.inner, Inner::Empty); + let inner = core::mem::replace(&mut self.inner, Inner::Empty); let x = match inner { Inner::Owned(x) => x, _ => Self::unreachable(), diff --git a/crates/wasmparser/src/validator/core/canonical.rs b/crates/wasmparser/src/validator/core/canonical.rs index 9a43fd3b16..884c40da58 100644 --- a/crates/wasmparser/src/validator/core/canonical.rs +++ b/crates/wasmparser/src/validator/core/canonical.rs @@ -111,7 +111,7 @@ pub(crate) struct TypeCanonicalizer<'a> { rec_group_len: u32, offset: usize, mode: CanonicalizationMode, - within_rec_group: Option>, + within_rec_group: Option>, } impl<'a> TypeCanonicalizer<'a> { diff --git a/crates/wasmparser/src/validator/names.rs b/crates/wasmparser/src/validator/names.rs index 52d61ecb93..379d4e87b9 100644 --- a/crates/wasmparser/src/validator/names.rs +++ b/crates/wasmparser/src/validator/names.rs @@ -1,12 +1,13 @@ //! Definitions of name-related helpers and newtypes, primarily for the //! component model. +use crate::prelude::*; use crate::{Result, WasmFeatures}; +use core::borrow::Borrow; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::ops::Deref; use semver::Version; -use std::borrow::Borrow; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::ops::Deref; /// Represents a kebab string slice used in validation. /// @@ -38,7 +39,7 @@ impl KebabStr { // Therefore transmuting `&str` to `&KebabStr` is safe. #[allow(unsafe_code)] unsafe { - std::mem::transmute::<_, &Self>(s.as_ref()) + core::mem::transmute::<_, &Self>(s.as_ref()) } } diff --git a/crates/wasmparser/src/validator/operators.rs b/crates/wasmparser/src/validator/operators.rs index 540420bf4c..be3305d34d 100644 --- a/crates/wasmparser/src/validator/operators.rs +++ b/crates/wasmparser/src/validator/operators.rs @@ -22,13 +22,14 @@ // confusing it's recommended to read over that section to see how it maps to // the various methods here. +use crate::prelude::*; use crate::{ limits::MAX_WASM_FUNCTION_LOCALS, ArrayType, BinaryReaderError, BlockType, BrTable, Catch, CompositeType, FieldType, FuncType, HeapType, Ieee32, Ieee64, MemArg, RefType, Result, StorageType, StructType, SubType, TryTable, UnpackedIndex, ValType, VisitOperator, WasmFeatures, WasmModuleResources, V128, }; -use std::ops::{Deref, DerefMut}; +use core::ops::{Deref, DerefMut}; pub(crate) struct OperatorValidator { pub(super) locals: Locals, @@ -154,15 +155,15 @@ enum MaybeType { // unit of storage, so assert that it doesn't exceed 4 bytes which is the // current expected size. const _: () = { - assert!(std::mem::size_of::() == 4); + assert!(core::mem::size_of::() == 4); }; -impl std::fmt::Display for MaybeType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for MaybeType { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { MaybeType::Bot => write!(f, "bot"), MaybeType::HeapBot => write!(f, "heap-bot"), - MaybeType::Type(ty) => std::fmt::Display::fmt(ty, f), + MaybeType::Type(ty) => core::fmt::Display::fmt(ty, f), } } } @@ -4073,8 +4074,8 @@ where } } -trait PreciseIterator: ExactSizeIterator + DoubleEndedIterator + Clone + std::fmt::Debug {} -impl PreciseIterator for T {} +trait PreciseIterator: ExactSizeIterator + DoubleEndedIterator + Clone + core::fmt::Debug {} +impl PreciseIterator for T {} impl Locals { /// Defines another group of `count` local variables of type `ty`. diff --git a/crates/wasmparser/src/validator/types.rs b/crates/wasmparser/src/validator/types.rs index 26e58aafff..5403b0cdff 100644 --- a/crates/wasmparser/src/validator/types.rs +++ b/crates/wasmparser/src/validator/types.rs @@ -4,24 +4,22 @@ use super::{ component::{ComponentState, ExternKind}, core::Module, }; +use crate::prelude::*; use crate::{validator::names::KebabString, HeapType, ValidatorId}; use crate::{ BinaryReaderError, CompositeType, Export, ExternalKind, FuncType, GlobalType, Import, Matches, MemoryType, PackedIndex, PrimitiveValType, RecGroup, RefType, Result, SubType, TableType, TypeRef, UnpackedIndex, ValType, WithRecGroup, }; -use indexmap::{IndexMap, IndexSet}; -use std::collections::hash_map::Entry; -use std::collections::{HashMap, HashSet}; -use std::ops::{Index, Range}; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::{ +use alloc::sync::Arc; +use core::ops::{Deref, DerefMut, Index, Range}; +use core::sync::atomic::{AtomicUsize, Ordering}; +use core::{ borrow::Borrow, hash::{Hash, Hasher}, mem, - ops::{Deref, DerefMut}, - sync::Arc, }; +use hashbrown::hash_map::Entry; /// The maximum number of parameters in the canonical ABI that can be passed by value. /// @@ -145,7 +143,7 @@ fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredT /// Any id that can be used to get a type from a `Types`. // // Or, internally, from a `TypeList`. -pub trait TypeIdentifier: std::fmt::Debug + Copy + Eq + Sized + 'static { +pub trait TypeIdentifier: core::fmt::Debug + Copy + Eq + Sized + 'static { /// The data pointed to by this type of id. type Data: TypeData; @@ -172,7 +170,7 @@ pub trait TypeIdentifier: std::fmt::Debug + Copy + Eq + Sized + 'static { /// /// This is the data that can be retreived by indexing with the associated /// [`TypeIdentifier`]. -pub trait TypeData: std::fmt::Debug { +pub trait TypeData: core::fmt::Debug { /// The identifier for this type data. type Id: TypeIdentifier; @@ -241,7 +239,7 @@ macro_rules! define_type_id { // The size of type IDs was seen to have a large-ish impact in #844, so // this assert ensures that it stays relatively small. const _: () = { - assert!(std::mem::size_of::<$name>() <= 4); + assert!(core::mem::size_of::<$name>() <= 4); }; }; } @@ -267,7 +265,7 @@ pub struct CoreTypeId { } const _: () = { - assert!(std::mem::size_of::() <= 4); + assert!(core::mem::size_of::() <= 4); }; impl TypeIdentifier for CoreTypeId { @@ -656,7 +654,7 @@ pub struct ComponentDefinedTypeId { } const _: () = { - assert!(std::mem::size_of::() <= 8); + assert!(core::mem::size_of::() <= 8); }; impl TypeIdentifier for ComponentDefinedTypeId { @@ -2887,7 +2885,7 @@ impl TypeList { }); TypeList { - alias_mappings: HashMap::new(), + alias_mappings: HashMap::default(), alias_counter: self.alias_counter, alias_snapshots: self.alias_snapshots.clone(), core_types: self.core_types.commit(), @@ -3211,7 +3209,7 @@ impl TypeAlloc { ComponentDefinedType::Flags(_) | ComponentDefinedType::Enum(_) | ComponentDefinedType::Record(_) - | ComponentDefinedType::Variant(_) => set.contains(&id.into()), + | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)), // All types below here are allowed to be anonymous, but their // own components must be appropriately named. @@ -3234,7 +3232,7 @@ impl TypeAlloc { // own/borrow themselves don't have to be named, but the resource // they refer to must be named. ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => { - set.contains(&(*id).into()) + set.contains(&ComponentAnyTypeId::from(*id)) } } } @@ -3561,7 +3559,7 @@ impl Remapping { fn remap_id(&self, id: &mut T) -> Option where T: Copy + Into + TryFrom, - T::Error: std::fmt::Debug, + T::Error: core::fmt::Debug, { let old: ComponentAnyTypeId = (*id).into(); let new = self.types.get(&old)?; diff --git a/crates/wasmprinter/Cargo.toml b/crates/wasmprinter/Cargo.toml index 3cb1c4dd6f..90859b7432 100644 --- a/crates/wasmprinter/Cargo.toml +++ b/crates/wasmprinter/Cargo.toml @@ -17,7 +17,7 @@ workspace = true [dependencies] anyhow = { workspace = true } -wasmparser = { workspace = true } +wasmparser = { workspace = true, features = ['std'] } [dev-dependencies] diff = "0.1" diff --git a/crates/wit-parser/Cargo.toml b/crates/wit-parser/Cargo.toml index 34573d42b5..dd5eb92160 100644 --- a/crates/wit-parser/Cargo.toml +++ b/crates/wit-parser/Cargo.toml @@ -18,13 +18,13 @@ workspace = true [dependencies] id-arena = "2" anyhow = { workspace = true } -indexmap = { workspace = true } +indexmap = { workspace = true, features = ['std'] } unicode-xid = "0.2.2" log = { workspace = true } semver = { workspace = true } serde = { workspace = true, optional = true } serde_derive = { workspace = true, optional = true } -wasmparser = { workspace = true, optional = true } +wasmparser = { workspace = true, optional = true, features = ['std'] } serde_json = { workspace = true, optional = true } wat = { workspace = true, optional = true } diff --git a/crates/wit-parser/src/decoding.rs b/crates/wit-parser/src/decoding.rs index 1fbb78f641..d36235adea 100644 --- a/crates/wit-parser/src/decoding.rs +++ b/crates/wit-parser/src/decoding.rs @@ -585,7 +585,7 @@ impl WitPackageDecoder<'_> { fn decode_interface<'a>( &mut self, name: &str, - imports: &IndexMap, + imports: &wasmparser::map::IndexMap, ty: &types::ComponentInstanceType, fields: &mut PackageFields<'a>, ) -> Result {