use bitflags::bitflags;
macro_rules! define_wasm_features {
(
$(#[$outer:meta])*
pub struct WasmFeatures: $repr:ty {
$(
$(#[$inner:ident $($args:tt)*])*
pub $field:ident: $const:ident($flag:expr) = $default:expr;
)*
}
) => {
bitflags! {
$(#[$outer])*
pub struct WasmFeatures: $repr {
$(
$(#[$inner $($args)*])*
#[doc = "\nDefaults to `"]
#[doc = stringify!($default)]
#[doc = "`.\n"]
const $const = $flag;
)*
}
}
impl Default for WasmFeatures {
#[inline]
fn default() -> Self {
let mut features = WasmFeatures::empty();
$(
features.set(WasmFeatures::$const, $default);
)*
features
}
}
impl WasmFeatures {
#[inline]
pub fn from_inflated(inflated: WasmFeaturesInflated) -> Self {
let mut features = WasmFeatures::empty();
$(
features.set(WasmFeatures::$const, inflated.$field);
)*
features
}
#[inline]
pub fn inflate(&self) -> WasmFeaturesInflated {
WasmFeaturesInflated {
$(
$field: self.$field(),
)*
}
}
$(
#[inline]
pub fn $field(&self) -> bool {
self.contains(WasmFeatures::$const)
}
)*
}
pub struct WasmFeaturesInflated {
$(
$(#[$inner $($args)*])*
#[doc = "\nDefaults to `"]
#[doc = stringify!($default)]
#[doc = "`.\n"]
pub $field: bool,
)*
}
};
}
define_wasm_features! {
#[derive(Hash, Debug, Copy, Clone, Eq, PartialEq)]
pub struct WasmFeatures: u32 {
pub mutable_global: MUTABLE_GLOBAL(1) = true;
pub saturating_float_to_int: SATURATING_FLOAT_TO_INT(1 << 1) = true;
/// The WebAssembly `sign-extension-ops` proposal.
pub sign_extension: SIGN_EXTENSION(1 << 2) = true;
/// The WebAssembly reference types proposal.
pub reference_types: REFERENCE_TYPES(1 << 3) = true;
/// The WebAssembly multi-value proposal.
pub multi_value: MULTI_VALUE(1 << 4) = true;
/// The WebAssembly bulk memory operations proposal.
pub bulk_memory: BULK_MEMORY(1 << 5) = true;
/// The WebAssembly SIMD proposal.
pub simd: SIMD(1 << 6) = true;
/// The WebAssembly Relaxed SIMD proposal.
pub relaxed_simd: RELAXED_SIMD(1 << 7) = true;
/// The WebAssembly threads proposal.
pub threads: THREADS(1 << 8) = true;
/// The WebAssembly shared-everything-threads proposal; includes new
/// component model built-ins.
pub shared_everything_threads: SHARED_EVERYTHING_THREADS(1 << 9) = false;
/// The WebAssembly tail-call proposal.
pub tail_call: TAIL_CALL(1 << 10) = true;
/// Whether or not floating-point instructions are enabled.
///
/// This is enabled by default can be used to disallow floating-point
/// operators and types.
///
/// This does not correspond to a WebAssembly proposal but is instead
/// intended for embeddings which have stricter-than-usual requirements
/// about execution. Floats in WebAssembly can have different NaN patterns
/// across hosts which can lead to host-dependent execution which some
/// runtimes may not desire.
pub floats: FLOATS(1 << 11) = true;
/// The WebAssembly multi memory proposal.
pub multi_memory: MULTI_MEMORY(1 << 12) = true;
/// The WebAssembly exception handling proposal.
pub exceptions: EXCEPTIONS(1 << 13) = true;
/// The WebAssembly memory64 proposal.
pub memory64: MEMORY64(1 << 14) = false;
/// The WebAssembly extended_const proposal.
pub extended_const: EXTENDED_CONST(1 << 15) = true;
/// The WebAssembly component model proposal.
pub component_model: COMPONENT_MODEL(1 << 16) = true;
/// The WebAssembly typed function references proposal.
pub function_references: FUNCTION_REFERENCES(1 << 17) = true;
/// The WebAssembly memory control proposal.
pub memory_control: MEMORY_CONTROL(1 << 18) = false;
/// The WebAssembly gc proposal.
pub gc: GC(1 << 19) = true;
/// The WebAssembly [custom-page-sizes
/// proposal](https://github.com/WebAssembly/custom-page-sizes).
pub custom_page_sizes: CUSTOM_PAGE_SIZES(1 << 20) = false;
/// Support for the `value` type in the component model proposal.
pub component_model_values: COMPONENT_MODEL_VALUES(1 << 21) = false;
/// Support for the nested namespaces and projects in component model names.
pub component_model_nested_names: COMPONENT_MODEL_NESTED_NAMES(1 << 22) = false;
/// Support for more than 32 flags per-type in the component model.
pub component_model_more_flags: COMPONENT_MODEL_MORE_FLAGS(1 << 23) = false;
/// Support for multiple return values in a component model function.
pub component_model_multiple_returns: COMPONENT_MODEL_MULTIPLE_RETURNS(1 << 24) = false;
/// The WebAssembly legacy exception handling proposal (phase 1)
///
/// # Note
///
/// Support this feature as long as all leading browsers also support it
/// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
pub legacy_exceptions: LEGACY_EXCEPTIONS(1 << 25) = false;
/// Whether or not gc types are enabled.
///
/// This feature does not correspond to any WebAssembly proposal nor
/// concept in the specification itself. This is intended to assist
/// embedders in disabling support for GC types at validation time. For
/// example if an engine wants to support all of WebAssembly except
/// a runtime garbage collector it could disable this feature.
///
/// This features is enabled by default and is used to gate types such
/// as `externref` or `anyref`. Note that the requisite WebAssembly
/// proposal must also be enabled for types like `externref`, meaning
/// that it requires both `REFERENCE_TYPES` and `GC_TYPE` to be enabled.
///
/// Note that the `funcref` and `exnref` types are not gated by this
/// feature. Those are expected to not require a full garbage collector
/// so are not gated by this.
pub gc_types: GC_TYPES(1 << 26) = true;
}
}
impl WasmFeatures {
/// Returns the feature set associated with the 1.0 version of the
/// WebAssembly specification or the "MVP" feature set.
pub fn wasm1() -> WasmFeatures {
WasmFeatures::FLOATS | WasmFeatures::GC_TYPES
}
/// Returns the feature set associated with the 2.0 version of the
/// WebAssembly specification.
pub fn wasm2() -> WasmFeatures {
WasmFeatures::wasm1()
| WasmFeatures::BULK_MEMORY
| WasmFeatures::REFERENCE_TYPES
| WasmFeatures::SIGN_EXTENSION
| WasmFeatures::MUTABLE_GLOBAL
| WasmFeatures::SATURATING_FLOAT_TO_INT
| WasmFeatures::MULTI_VALUE
| WasmFeatures::SIMD
}
}
impl From<WasmFeaturesInflated> for WasmFeatures {
#[inline]
fn from(inflated: WasmFeaturesInflated) -> Self {
Self::from_inflated(inflated)
}
}
impl From<WasmFeatures> for WasmFeaturesInflated {
#[inline]
fn from(features: WasmFeatures) -> Self {
features.inflate()
}
}