use super::CORE_TYPE_SORT; use crate::{ encode_section, Alias, ComponentExportKind, ComponentOuterAliasKind, ComponentSection, ComponentSectionId, ComponentTypeRef, Encode, EntityType, ValType, }; /// Represents the type of a core module. #[derive(Debug, Clone, Default)] pub struct ModuleType { bytes: Vec, num_added: u32, types_added: u32, } impl ModuleType { /// Creates a new core module type. pub fn new() -> Self { Self::default() } /// Defines an import in this module type. pub fn import(&mut self, module: &str, name: &str, ty: EntityType) -> &mut Self { crate::component::imports::push_extern_name_byte(&mut self.bytes, name); module.encode(&mut self.bytes); name.encode(&mut self.bytes); ty.encode(&mut self.bytes); self.num_added += 1; self } /// Define a type in this module type. /// /// The returned encoder must be used before adding another definition. #[must_use = "the encoder must be used to encode the type"] pub fn ty(&mut self) -> CoreTypeEncoder { self.bytes.push(0x01); self.num_added += 1; self.types_added += 1; CoreTypeEncoder(&mut self.bytes) } /// Defines an outer core type alias in this module type. pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self { self.bytes.push(0x02); self.bytes.push(CORE_TYPE_SORT); self.bytes.push(0x01); // outer count.encode(&mut self.bytes); index.encode(&mut self.bytes); self.num_added += 1; self.types_added += 1; self } /// Defines an export in this module type. pub fn export(&mut self, name: &str, ty: EntityType) -> &mut Self { self.bytes.push(0x03); name.encode(&mut self.bytes); ty.encode(&mut self.bytes); self.num_added += 1; self } /// Gets the number of types that have been added to this module type. pub fn type_count(&self) -> u32 { self.types_added } } impl Encode for ModuleType { fn encode(&self, sink: &mut Vec) { sink.push(0x50); self.num_added.encode(sink); sink.extend(&self.bytes); } } /// Used to encode core types. #[derive(Debug)] pub struct CoreTypeEncoder<'a>(pub(crate) &'a mut Vec); impl<'a> CoreTypeEncoder<'a> { /// Define a function type. pub fn function(self, params: P, results: R) where P: IntoIterator, P::IntoIter: ExactSizeIterator, R: IntoIterator, R::IntoIter: ExactSizeIterator, { let params = params.into_iter(); let results = results.into_iter(); self.0.push(0x60); params.len().encode(self.0); params.for_each(|p| p.encode(self.0)); results.len().encode(self.0); results.for_each(|p| p.encode(self.0)); } /// Define a module type. pub fn module(self, ty: &ModuleType) { ty.encode(self.0); } } /// An encoder for the core type section of WebAssembly components. /// /// # Example /// /// ```rust /// use wasm_encoder::{Component, CoreTypeSection, ModuleType}; /// /// let mut types = CoreTypeSection::new(); /// /// types.module(&ModuleType::new()); /// /// let mut component = Component::new(); /// component.section(&types); /// /// let bytes = component.finish(); /// ``` #[derive(Clone, Debug, Default)] pub struct CoreTypeSection { bytes: Vec, num_added: u32, } impl CoreTypeSection { /// Create a new core type section encoder. pub fn new() -> Self { Self::default() } /// The number of types in the section. pub fn len(&self) -> u32 { self.num_added } /// Determines if the section is empty. pub fn is_empty(&self) -> bool { self.num_added == 0 } /// Encode a type into this section. /// /// The returned encoder must be finished before adding another type. #[must_use = "the encoder must be used to encode the type"] pub fn ty(&mut self) -> CoreTypeEncoder<'_> { self.num_added += 1; CoreTypeEncoder(&mut self.bytes) } /// Define a function type in this type section. pub fn function(&mut self, params: P, results: R) -> &mut Self where P: IntoIterator, P::IntoIter: ExactSizeIterator, R: IntoIterator, R::IntoIter: ExactSizeIterator, { self.ty().function(params, results); self } /// Define a module type in this type section. /// /// Currently this is only used for core type sections in components. pub fn module(&mut self, ty: &ModuleType) -> &mut Self { self.ty().module(ty); self } } impl Encode for CoreTypeSection { fn encode(&self, sink: &mut Vec) { encode_section(sink, self.num_added, &self.bytes); } } impl ComponentSection for CoreTypeSection { fn id(&self) -> u8 { ComponentSectionId::CoreType.into() } } /// Represents a component type. #[derive(Debug, Clone, Default)] pub struct ComponentType { bytes: Vec, num_added: u32, core_types_added: u32, types_added: u32, instances_added: u32, } impl ComponentType { /// Creates a new component type. pub fn new() -> Self { Self::default() } /// Define a core type in this component type. /// /// The returned encoder must be used before adding another definition. #[must_use = "the encoder must be used to encode the type"] pub fn core_type(&mut self) -> CoreTypeEncoder { self.bytes.push(0x00); self.num_added += 1; self.core_types_added += 1; CoreTypeEncoder(&mut self.bytes) } /// Define a type in this component type. /// /// The returned encoder must be used before adding another definition. #[must_use = "the encoder must be used to encode the type"] pub fn ty(&mut self) -> ComponentTypeEncoder { self.bytes.push(0x01); self.num_added += 1; self.types_added += 1; ComponentTypeEncoder(&mut self.bytes) } /// Defines an alias for an exported item of a prior instance or an /// outer type. pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self { self.bytes.push(0x02); alias.encode(&mut self.bytes); self.num_added += 1; match &alias { Alias::InstanceExport { kind: ComponentExportKind::Type, .. } | Alias::Outer { kind: ComponentOuterAliasKind::Type, .. } => self.types_added += 1, Alias::Outer { kind: ComponentOuterAliasKind::CoreType, .. } => self.core_types_added += 1, Alias::InstanceExport { kind: ComponentExportKind::Instance, .. } => self.instances_added += 1, _ => {} } self } /// Defines an import in this component type. pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self { self.bytes.push(0x03); crate::component::imports::push_extern_name_byte(&mut self.bytes, name); name.encode(&mut self.bytes); ty.encode(&mut self.bytes); self.num_added += 1; match ty { ComponentTypeRef::Type(..) => self.types_added += 1, ComponentTypeRef::Instance(..) => self.instances_added += 1, _ => {} } self } /// Defines an export in this component type. pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self { self.bytes.push(0x04); crate::component::imports::push_extern_name_byte(&mut self.bytes, name); name.encode(&mut self.bytes); ty.encode(&mut self.bytes); self.num_added += 1; match ty { ComponentTypeRef::Type(..) => self.types_added += 1, ComponentTypeRef::Instance(..) => self.instances_added += 1, _ => {} } self } /// Gets the number of core types that have been added to this component type. pub fn core_type_count(&self) -> u32 { self.core_types_added } /// Gets the number of types that have been added or aliased in this component type. pub fn type_count(&self) -> u32 { self.types_added } /// Gets the number of instances that have been defined in this component /// type through imports, exports, or aliases. pub fn instance_count(&self) -> u32 { self.instances_added } } impl Encode for ComponentType { fn encode(&self, sink: &mut Vec) { sink.push(0x41); self.num_added.encode(sink); sink.extend(&self.bytes); } } /// Represents an instance type. #[derive(Debug, Clone, Default)] pub struct InstanceType(ComponentType); impl InstanceType { /// Creates a new instance type. pub fn new() -> Self { Self::default() } /// Define a core type in this instance type. /// /// The returned encoder must be used before adding another definition. #[must_use = "the encoder must be used to encode the type"] pub fn core_type(&mut self) -> CoreTypeEncoder { self.0.core_type() } /// Define a type in this instance type. /// /// The returned encoder must be used before adding another definition. #[must_use = "the encoder must be used to encode the type"] pub fn ty(&mut self) -> ComponentTypeEncoder { self.0.ty() } /// Defines an outer core type alias in this component type. pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self { self.0.alias(alias); self } /// Defines an export in this instance type. pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self { self.0.export(name, ty); self } /// Gets the number of core types that have been added to this instance type. pub fn core_type_count(&self) -> u32 { self.0.core_types_added } /// Gets the number of types that have been added or aliased in this instance type. pub fn type_count(&self) -> u32 { self.0.types_added } /// Gets the number of instances that have been imported or exported or /// aliased in this instance type. pub fn instance_count(&self) -> u32 { self.0.instances_added } /// Returns whether or not this instance type is empty. pub fn is_empty(&self) -> bool { self.0.num_added == 0 } /// Returns the number of entries added to this instance types. pub fn len(&self) -> u32 { self.0.num_added } } impl Encode for InstanceType { fn encode(&self, sink: &mut Vec) { sink.push(0x42); self.0.num_added.encode(sink); sink.extend(&self.0.bytes); } } /// Used to encode component function types. #[derive(Debug)] pub struct ComponentFuncTypeEncoder<'a>(&'a mut Vec); impl<'a> ComponentFuncTypeEncoder<'a> { fn new(sink: &'a mut Vec) -> Self { sink.push(0x40); Self(sink) } /// Defines named parameters. /// /// Parameters must be defined before defining results. pub fn params<'b, P, T>(&mut self, params: P) -> &mut Self where P: IntoIterator, P::IntoIter: ExactSizeIterator, T: Into, { let params = params.into_iter(); params.len().encode(self.0); for (name, ty) in params { name.encode(self.0); ty.into().encode(self.0); } self } /// Defines a single unnamed result. /// /// This method cannot be used with `results`. pub fn result(&mut self, ty: impl Into) -> &mut Self { self.0.push(0x00); ty.into().encode(self.0); self } /// Defines named results. /// /// This method cannot be used with `result`. pub fn results<'b, R, T>(&mut self, results: R) -> &mut Self where R: IntoIterator, R::IntoIter: ExactSizeIterator, T: Into, { self.0.push(0x01); let results = results.into_iter(); results.len().encode(self.0); for (name, ty) in results { name.encode(self.0); ty.into().encode(self.0); } self } } /// Used to encode component and instance types. #[derive(Debug)] pub struct ComponentTypeEncoder<'a>(&'a mut Vec); impl<'a> ComponentTypeEncoder<'a> { /// Define a component type. pub fn component(self, ty: &ComponentType) { ty.encode(self.0); } /// Define an instance type. pub fn instance(self, ty: &InstanceType) { ty.encode(self.0); } /// Define a function type. pub fn function(self) -> ComponentFuncTypeEncoder<'a> { ComponentFuncTypeEncoder::new(self.0) } /// Define a defined component type. /// /// The returned encoder must be used before adding another type. #[must_use = "the encoder must be used to encode the type"] pub fn defined_type(self) -> ComponentDefinedTypeEncoder<'a> { ComponentDefinedTypeEncoder(self.0) } /// Define a resource type. pub fn resource(self, rep: ValType, dtor: Option) { self.0.push(0x3f); rep.encode(self.0); match dtor { Some(i) => { self.0.push(0x01); i.encode(self.0); } None => self.0.push(0x00), } } } /// Represents a primitive component value type. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum PrimitiveValType { /// The type is a boolean. Bool, /// The type is a signed 8-bit integer. S8, /// The type is an unsigned 8-bit integer. U8, /// The type is a signed 16-bit integer. S16, /// The type is an unsigned 16-bit integer. U16, /// The type is a signed 32-bit integer. S32, /// The type is an unsigned 32-bit integer. U32, /// The type is a signed 64-bit integer. S64, /// The type is an unsigned 64-bit integer. U64, /// The type is a 32-bit floating point number with only one NaN. F32, /// The type is a 64-bit floating point number with only one NaN. F64, /// The type is a Unicode character. Char, /// The type is a string. String, } impl Encode for PrimitiveValType { fn encode(&self, sink: &mut Vec) { sink.push(match self { Self::Bool => 0x7f, Self::S8 => 0x7e, Self::U8 => 0x7d, Self::S16 => 0x7c, Self::U16 => 0x7b, Self::S32 => 0x7a, Self::U32 => 0x79, Self::S64 => 0x78, Self::U64 => 0x77, Self::F32 => 0x76, Self::F64 => 0x75, Self::Char => 0x74, Self::String => 0x73, }); } } #[cfg(feature = "wasmparser")] impl From for PrimitiveValType { fn from(ty: wasmparser::PrimitiveValType) -> Self { match ty { wasmparser::PrimitiveValType::Bool => PrimitiveValType::Bool, wasmparser::PrimitiveValType::S8 => PrimitiveValType::S8, wasmparser::PrimitiveValType::U8 => PrimitiveValType::U8, wasmparser::PrimitiveValType::S16 => PrimitiveValType::S16, wasmparser::PrimitiveValType::U16 => PrimitiveValType::U16, wasmparser::PrimitiveValType::S32 => PrimitiveValType::S32, wasmparser::PrimitiveValType::U32 => PrimitiveValType::U32, wasmparser::PrimitiveValType::S64 => PrimitiveValType::S64, wasmparser::PrimitiveValType::U64 => PrimitiveValType::U64, wasmparser::PrimitiveValType::F32 => PrimitiveValType::F32, wasmparser::PrimitiveValType::F64 => PrimitiveValType::F64, wasmparser::PrimitiveValType::Char => PrimitiveValType::Char, wasmparser::PrimitiveValType::String => PrimitiveValType::String, } } } /// Represents a component value type. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ComponentValType { /// The value is a primitive type. Primitive(PrimitiveValType), /// The value is to a defined value type. /// /// The type index must be to a value type. Type(u32), } impl Encode for ComponentValType { fn encode(&self, sink: &mut Vec) { match self { Self::Primitive(ty) => ty.encode(sink), Self::Type(index) => (*index as i64).encode(sink), } } } impl From for ComponentValType { fn from(ty: PrimitiveValType) -> Self { Self::Primitive(ty) } } /// Used for encoding component defined types. #[derive(Debug)] pub struct ComponentDefinedTypeEncoder<'a>(&'a mut Vec); impl ComponentDefinedTypeEncoder<'_> { /// Define a primitive value type. pub fn primitive(self, ty: PrimitiveValType) { ty.encode(self.0); } /// Define a record type. pub fn record<'a, F, T>(self, fields: F) where F: IntoIterator, F::IntoIter: ExactSizeIterator, T: Into, { let fields = fields.into_iter(); self.0.push(0x72); fields.len().encode(self.0); for (name, ty) in fields { name.encode(self.0); ty.into().encode(self.0); } } /// Define a variant type. pub fn variant<'a, C>(self, cases: C) where C: IntoIterator, Option)>, C::IntoIter: ExactSizeIterator, { let cases = cases.into_iter(); self.0.push(0x71); cases.len().encode(self.0); for (name, ty, refines) in cases { name.encode(self.0); ty.encode(self.0); refines.encode(self.0); } } /// Define a list type. pub fn list(self, ty: impl Into) { self.0.push(0x70); ty.into().encode(self.0); } /// Define a tuple type. pub fn tuple(self, types: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, T: Into, { let types = types.into_iter(); self.0.push(0x6F); types.len().encode(self.0); for ty in types { ty.into().encode(self.0); } } /// Define a flags type. pub fn flags<'a, I>(self, names: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, { let names = names.into_iter(); self.0.push(0x6E); names.len().encode(self.0); for name in names { name.encode(self.0); } } /// Define an enum type. pub fn enum_type<'a, I>(self, tags: I) where I: IntoIterator, I::IntoIter: ExactSizeIterator, { let tags = tags.into_iter(); self.0.push(0x6D); tags.len().encode(self.0); for tag in tags { tag.encode(self.0); } } /// Define an option type. pub fn option(self, ty: impl Into) { self.0.push(0x6B); ty.into().encode(self.0); } /// Define a result type. pub fn result(self, ok: Option, err: Option) { self.0.push(0x6A); ok.encode(self.0); err.encode(self.0); } /// Define a `own` handle type pub fn own(self, idx: u32) { self.0.push(0x69); idx.encode(self.0); } /// Define a `borrow` handle type pub fn borrow(self, idx: u32) { self.0.push(0x68); idx.encode(self.0); } } /// An encoder for the type section of WebAssembly components. /// /// # Example /// /// ```rust /// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType}; /// /// let mut types = ComponentTypeSection::new(); /// /// // Define a function type of `[string, string] -> string`. /// types /// .function() /// .params( /// [ /// ("a", PrimitiveValType::String), /// ("b", PrimitiveValType::String) /// ] /// ) /// .result(PrimitiveValType::String); /// /// let mut component = Component::new(); /// component.section(&types); /// /// let bytes = component.finish(); /// ``` #[derive(Clone, Debug, Default)] pub struct ComponentTypeSection { bytes: Vec, num_added: u32, } impl ComponentTypeSection { /// Create a new component type section encoder. pub fn new() -> Self { Self::default() } /// The number of types in the section. pub fn len(&self) -> u32 { self.num_added } /// Determines if the section is empty. pub fn is_empty(&self) -> bool { self.num_added == 0 } /// Encode a type into this section. /// /// The returned encoder must be finished before adding another type. #[must_use = "the encoder must be used to encode the type"] pub fn ty(&mut self) -> ComponentTypeEncoder<'_> { self.num_added += 1; ComponentTypeEncoder(&mut self.bytes) } /// Define a component type in this type section. pub fn component(&mut self, ty: &ComponentType) -> &mut Self { self.ty().component(ty); self } /// Define an instance type in this type section. pub fn instance(&mut self, ty: &InstanceType) -> &mut Self { self.ty().instance(ty); self } /// Define a function type in this type section. pub fn function(&mut self) -> ComponentFuncTypeEncoder<'_> { self.ty().function() } /// Add a component defined type to this type section. /// /// The returned encoder must be used before adding another type. #[must_use = "the encoder must be used to encode the type"] pub fn defined_type(&mut self) -> ComponentDefinedTypeEncoder<'_> { self.ty().defined_type() } /// Defines a new resource type. pub fn resource(&mut self, rep: ValType, dtor: Option) -> &mut Self { self.ty().resource(rep, dtor); self } } impl Encode for ComponentTypeSection { fn encode(&self, sink: &mut Vec) { encode_section(sink, self.num_added, &self.bytes); } } impl ComponentSection for ComponentTypeSection { fn id(&self) -> u8 { ComponentSectionId::Type.into() } }