summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasm-smith/src/component/encode.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wasm-smith/src/component/encode.rs')
-rw-r--r--third_party/rust/wasm-smith/src/component/encode.rs321
1 files changed, 321 insertions, 0 deletions
diff --git a/third_party/rust/wasm-smith/src/component/encode.rs b/third_party/rust/wasm-smith/src/component/encode.rs
new file mode 100644
index 0000000000..7963ecfae5
--- /dev/null
+++ b/third_party/rust/wasm-smith/src/component/encode.rs
@@ -0,0 +1,321 @@
+use std::borrow::Cow;
+
+use super::*;
+use wasm_encoder::{ComponentExportKind, ComponentOuterAliasKind, ExportKind};
+
+impl Component {
+ /// Encode this Wasm component into bytes.
+ pub fn to_bytes(&self) -> Vec<u8> {
+ self.encoded().finish()
+ }
+
+ fn encoded(&self) -> wasm_encoder::Component {
+ let mut component = wasm_encoder::Component::new();
+ for section in &self.sections {
+ section.encode(&mut component);
+ }
+ component
+ }
+}
+
+impl Section {
+ fn encode(&self, component: &mut wasm_encoder::Component) {
+ match self {
+ Self::Custom(sec) => sec.encode(component),
+ Self::CoreModule(module) => {
+ let bytes = module.to_bytes();
+ component.section(&wasm_encoder::RawSection {
+ id: wasm_encoder::ComponentSectionId::CoreModule as u8,
+ data: &bytes,
+ });
+ }
+ Self::CoreInstance(_) => todo!(),
+ Self::CoreType(sec) => sec.encode(component),
+ Self::Component(comp) => {
+ let bytes = comp.to_bytes();
+ component.section(&wasm_encoder::RawSection {
+ id: wasm_encoder::ComponentSectionId::Component as u8,
+ data: &bytes,
+ });
+ }
+ Self::Instance(_) => todo!(),
+ Self::Alias(_) => todo!(),
+ Self::Type(sec) => sec.encode(component),
+ Self::Canonical(sec) => sec.encode(component),
+ Self::Start(_) => todo!(),
+ Self::Import(sec) => sec.encode(component),
+ Self::Export(_) => todo!(),
+ }
+ }
+}
+
+impl CustomSection {
+ fn encode(&self, component: &mut wasm_encoder::Component) {
+ component.section(&wasm_encoder::CustomSection {
+ name: (&self.name).into(),
+ data: Cow::Borrowed(&self.data),
+ });
+ }
+}
+
+impl TypeSection {
+ fn encode(&self, component: &mut wasm_encoder::Component) {
+ let mut sec = wasm_encoder::ComponentTypeSection::new();
+ for ty in &self.types {
+ ty.encode(sec.ty());
+ }
+ component.section(&sec);
+ }
+}
+
+impl ImportSection {
+ fn encode(&self, component: &mut wasm_encoder::Component) {
+ let mut sec = wasm_encoder::ComponentImportSection::new();
+ for imp in &self.imports {
+ sec.import(&imp.name, imp.ty);
+ }
+ component.section(&sec);
+ }
+}
+
+impl CanonicalSection {
+ fn encode(&self, component: &mut wasm_encoder::Component) {
+ let mut sec = wasm_encoder::CanonicalFunctionSection::new();
+ for func in &self.funcs {
+ match func {
+ Func::CanonLift {
+ func_ty,
+ options,
+ core_func_index,
+ } => {
+ let options = translate_canon_opt(options);
+ sec.lift(*core_func_index, *func_ty, options);
+ }
+ Func::CanonLower {
+ options,
+ func_index,
+ } => {
+ let options = translate_canon_opt(options);
+ sec.lower(*func_index, options);
+ }
+ }
+ }
+ component.section(&sec);
+ }
+}
+
+impl CoreTypeSection {
+ fn encode(&self, component: &mut wasm_encoder::Component) {
+ let mut sec = wasm_encoder::CoreTypeSection::new();
+ for ty in &self.types {
+ ty.encode(sec.ty());
+ }
+ component.section(&sec);
+ }
+}
+
+impl CoreType {
+ fn encode(&self, enc: wasm_encoder::CoreTypeEncoder<'_>) {
+ match self {
+ Self::Func(ty) => {
+ enc.function(ty.params.iter().copied(), ty.results.iter().copied());
+ }
+ Self::Module(mod_ty) => {
+ let mut enc_mod_ty = wasm_encoder::ModuleType::new();
+ for def in &mod_ty.defs {
+ match def {
+ ModuleTypeDef::TypeDef(crate::core::CompositeType::Func(func_ty)) => {
+ enc_mod_ty.ty().function(
+ func_ty.params.iter().copied(),
+ func_ty.results.iter().copied(),
+ );
+ }
+ ModuleTypeDef::TypeDef(_) => {
+ unimplemented!("non-func types in a component's module type")
+ }
+ ModuleTypeDef::OuterAlias { count, i, kind } => match kind {
+ CoreOuterAliasKind::Type(_) => {
+ enc_mod_ty.alias_outer_core_type(*count, *i);
+ }
+ },
+ ModuleTypeDef::Import(imp) => {
+ enc_mod_ty.import(
+ &imp.module,
+ &imp.field,
+ crate::core::encode::translate_entity_type(&imp.entity_type),
+ );
+ }
+ ModuleTypeDef::Export(name, ty) => {
+ enc_mod_ty.export(name, crate::core::encode::translate_entity_type(ty));
+ }
+ }
+ }
+ enc.module(&enc_mod_ty);
+ }
+ }
+ }
+}
+
+impl Type {
+ fn encode(&self, enc: wasm_encoder::ComponentTypeEncoder<'_>) {
+ match self {
+ Self::Defined(ty) => {
+ ty.encode(enc.defined_type());
+ }
+ Self::Func(func_ty) => {
+ let mut f = enc.function();
+
+ f.params(func_ty.params.iter().map(|(name, ty)| (name.as_str(), *ty)));
+
+ if let Some(ty) = func_ty.unnamed_result_ty() {
+ f.result(ty);
+ } else {
+ f.results(
+ func_ty
+ .results
+ .iter()
+ .map(|(name, ty)| (name.as_deref().unwrap(), *ty)),
+ );
+ }
+ }
+ Self::Component(comp_ty) => {
+ let mut enc_comp_ty = wasm_encoder::ComponentType::new();
+ for def in &comp_ty.defs {
+ match def {
+ ComponentTypeDef::Import(imp) => {
+ enc_comp_ty.import(&imp.name, imp.ty);
+ }
+ ComponentTypeDef::CoreType(ty) => {
+ ty.encode(enc_comp_ty.core_type());
+ }
+ ComponentTypeDef::Type(ty) => {
+ ty.encode(enc_comp_ty.ty());
+ }
+ ComponentTypeDef::Export { name, url: _, ty } => {
+ enc_comp_ty.export(name, *ty);
+ }
+ ComponentTypeDef::Alias(a) => {
+ enc_comp_ty.alias(translate_alias(a));
+ }
+ }
+ }
+ enc.component(&enc_comp_ty);
+ }
+ Self::Instance(inst_ty) => {
+ let mut enc_inst_ty = wasm_encoder::InstanceType::new();
+ for def in &inst_ty.defs {
+ match def {
+ InstanceTypeDecl::CoreType(ty) => {
+ ty.encode(enc_inst_ty.core_type());
+ }
+ InstanceTypeDecl::Type(ty) => {
+ ty.encode(enc_inst_ty.ty());
+ }
+ InstanceTypeDecl::Export { name, url: _, ty } => {
+ enc_inst_ty.export(name, *ty);
+ }
+ InstanceTypeDecl::Alias(a) => {
+ enc_inst_ty.alias(translate_alias(a));
+ }
+ }
+ }
+ enc.instance(&enc_inst_ty);
+ }
+ }
+ }
+}
+
+impl DefinedType {
+ fn encode(&self, enc: wasm_encoder::ComponentDefinedTypeEncoder<'_>) {
+ match self {
+ Self::Primitive(ty) => enc.primitive(*ty),
+ Self::Record(ty) => {
+ enc.record(ty.fields.iter().map(|(name, ty)| (name.as_str(), *ty)));
+ }
+ Self::Variant(ty) => {
+ enc.variant(
+ ty.cases
+ .iter()
+ .map(|(name, ty, refines)| (name.as_str(), *ty, *refines)),
+ );
+ }
+ Self::List(ty) => {
+ enc.list(ty.elem_ty);
+ }
+ Self::Tuple(ty) => {
+ enc.tuple(ty.fields.iter().copied());
+ }
+ Self::Flags(ty) => {
+ enc.flags(ty.fields.iter().map(|f| f.as_str()));
+ }
+ Self::Enum(ty) => {
+ enc.enum_type(ty.variants.iter().map(|v| v.as_str()));
+ }
+ Self::Option(ty) => {
+ enc.option(ty.inner_ty);
+ }
+ Self::Result(ty) => {
+ enc.result(ty.ok_ty, ty.err_ty);
+ }
+ }
+ }
+}
+
+fn translate_canon_opt(options: &[CanonOpt]) -> Vec<wasm_encoder::CanonicalOption> {
+ options
+ .iter()
+ .map(|o| match o {
+ CanonOpt::StringUtf8 => wasm_encoder::CanonicalOption::UTF8,
+ CanonOpt::StringUtf16 => wasm_encoder::CanonicalOption::UTF16,
+ CanonOpt::StringLatin1Utf16 => wasm_encoder::CanonicalOption::CompactUTF16,
+ CanonOpt::Memory(idx) => wasm_encoder::CanonicalOption::Memory(*idx),
+ CanonOpt::Realloc(idx) => wasm_encoder::CanonicalOption::Realloc(*idx),
+ CanonOpt::PostReturn(idx) => wasm_encoder::CanonicalOption::PostReturn(*idx),
+ })
+ .collect()
+}
+
+fn translate_alias(alias: &Alias) -> wasm_encoder::Alias<'_> {
+ match alias {
+ Alias::InstanceExport {
+ instance,
+ name,
+ kind,
+ } => wasm_encoder::Alias::InstanceExport {
+ instance: *instance,
+ name,
+ kind: match kind {
+ InstanceExportAliasKind::Module => ComponentExportKind::Module,
+ InstanceExportAliasKind::Component => ComponentExportKind::Component,
+ InstanceExportAliasKind::Instance => ComponentExportKind::Instance,
+ InstanceExportAliasKind::Func => ComponentExportKind::Func,
+ InstanceExportAliasKind::Value => ComponentExportKind::Value,
+ },
+ },
+ Alias::CoreInstanceExport {
+ instance,
+ name,
+ kind,
+ } => wasm_encoder::Alias::CoreInstanceExport {
+ instance: *instance,
+ name,
+ kind: match kind {
+ CoreInstanceExportAliasKind::Func => ExportKind::Func,
+ CoreInstanceExportAliasKind::Table => ExportKind::Table,
+ CoreInstanceExportAliasKind::Global => ExportKind::Global,
+ CoreInstanceExportAliasKind::Memory => ExportKind::Memory,
+ CoreInstanceExportAliasKind::Tag => ExportKind::Tag,
+ },
+ },
+ Alias::Outer { count, i, kind } => wasm_encoder::Alias::Outer {
+ count: *count,
+ index: *i,
+ kind: match kind {
+ OuterAliasKind::Module => ComponentOuterAliasKind::CoreModule,
+ OuterAliasKind::Component => ComponentOuterAliasKind::Component,
+ OuterAliasKind::Type(_) => ComponentOuterAliasKind::Type,
+ OuterAliasKind::CoreType(_) => ComponentOuterAliasKind::CoreType,
+ },
+ },
+ }
+}