use wasm_encoder::{
Alias, CanonicalFunctionSection, CanonicalOption, Component, ComponentAliasSection,
ComponentExportKind, ComponentExportSection, ComponentSectionId, ComponentTypeSection,
ComponentValType, ExportKind, InstanceSection, ModuleArg, ModuleSection, PrimitiveValType,
RawSection,
};
use crate::Config;
use super::{module::gen_module, template::TemplateGenerator};
pub fn gen_component(config: &Config, template: &TemplateGenerator) -> Component {
let mut component = Component::new();
let allocator = gen_allocator();
let id = ComponentSectionId::CoreModule.into();
let data = allocator.as_slice();
component.section(&RawSection { id, data });
let allocator_module_index = 0;
let module = gen_module(config, template);
component.section(&ModuleSection(&module));
let inner_module_index = 1;
let mut instances = InstanceSection::new();
instances.instantiate::<Vec<(&str, ModuleArg)>, &str>(allocator_module_index, vec![]);
instances.instantiate(
inner_module_index,
[("allocator", ModuleArg::Instance(allocator_module_index))].into_iter(),
);
component.section(&instances);
let mut aliases = ComponentAliasSection::new();
aliases.alias(Alias::CoreInstanceExport {
instance: allocator_module_index,
kind: ExportKind::Memory,
name: "memory",
});
aliases.alias(Alias::CoreInstanceExport {
instance: allocator_module_index,
kind: ExportKind::Func,
name: "realloc",
});
aliases.alias(Alias::CoreInstanceExport {
instance: inner_module_index,
kind: ExportKind::Func,
name: &config.export_func_name,
});
component.section(&aliases);
let types = template.params().record_type();
let params_type_index = 0;
component.section(&types);
let mut exports = ComponentExportSection::new();
exports.export("params", ComponentExportKind::Type, params_type_index, None);
let params_export_index = 1;
component.section(&exports);
let mut types = ComponentTypeSection::new();
types
.function()
.params([("params", ComponentValType::Type(params_export_index))])
.result(ComponentValType::Primitive(PrimitiveValType::String));
let apply_type_index = 2;
component.section(&types);
let mut functions = CanonicalFunctionSection::new();
functions.lift(
1,
apply_type_index,
[
CanonicalOption::UTF8,
CanonicalOption::Memory(0),
CanonicalOption::Realloc(0),
],
);
component.section(&functions);
let mut exports = ComponentExportSection::new();
exports.export(&config.export_func_name, ComponentExportKind::Func, 0, None);
component.section(&exports);
component
}
pub fn gen_allocator() -> Vec<u8> {
let wat = include_str!("../../allocator.wat");
wat::parse_str(wat).unwrap()
}