use super::{
ComponentSection, SectionId, TypeRef, ALIAS_KIND_OUTER, ALIAS_KIND_OUTER_MODULE,
ALIAS_KIND_OUTER_TYPE,
};
use crate::{encoders, ValType};
const TYPE_INSTANCE: u8 = 0x7f;
const TYPE_MODULE: u8 = 0x7e;
const TYPE_FUNCTION: u8 = 0x7d;
const TYPE_ADAPTER_FUNCTION: u8 = 0x7c;
const COMPOUND_INTERFACE_TYPE_LIST: u8 = 0x7b;
const COMPOUND_INTERFACE_TYPE_RECORD: u8 = 0x7a;
const COMPOUND_INTERFACE_TYPE_VARIANT: u8 = 0x79;
const COMPOUND_INTERFACE_TYPE_TUPLE: u8 = 0x78;
const COMPOUND_INTERFACE_TYPE_FLAGS: u8 = 0x77;
const COMPOUND_INTERFACE_TYPE_ENUM: u8 = 0x76;
const COMPOUND_INTERFACE_TYPE_UNION: u8 = 0x75;
const COMPOUND_INTERFACE_TYPE_OPTIONAL: u8 = 0x74;
const COMPOUND_INTERFACE_TYPE_EXPECTED: u8 = 0x73;
const COMPOUND_INTERFACE_TYPE_NAMED: u8 = 0x72;
const INTERFACE_TYPE_BOOL: u8 = 0x71;
const INTERFACE_TYPE_S8: u8 = 0x70;
const INTERFACE_TYPE_U8: u8 = 0x6f;
const INTERFACE_TYPE_S16: u8 = 0x6e;
const INTERFACE_TYPE_U16: u8 = 0x6d;
const INTERFACE_TYPE_S32: u8 = 0x6c;
const INTERFACE_TYPE_U32: u8 = 0x6b;
const INTERFACE_TYPE_S64: u8 = 0x6a;
const INTERFACE_TYPE_U64: u8 = 0x69;
const INTERFACE_TYPE_F32: u8 = 0x68;
const INTERFACE_TYPE_F64: u8 = 0x67;
const INTERFACE_TYPE_CHAR: u8 = 0x66;
const INTERFACE_TYPE_STRING: u8 = 0x65;
const INSTANCE_TYPEDEF_TYPE: u8 = 0x01;
const INSTANCE_TYPEDEF_ALIAS: u8 = 0x05;
const INSTANCE_TYPEDEF_EXPORT: u8 = 0x06;
const MODULE_TYPEDEF_TYPE: u8 = 0x01;
const MODULE_TYPEDEF_ALIAS: u8 = 0x05;
const MODULE_TYPEDEF_EXPORT: u8 = 0x06;
const MODULE_TYPEDEF_IMPORT: u8 = 0x02;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DefinitionKind {
Instance = 0,
Module = 1,
Function = 2,
Table = 3,
Memory = 4,
Global = 5,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OuterAliasIndex {
Module(u32),
Type(u32),
}
impl OuterAliasIndex {
pub(crate) fn encode(&self, bytes: &mut Vec<u8>) {
match self {
Self::Module(index) => {
bytes.extend(encoders::u32(*index));
bytes.push(ALIAS_KIND_OUTER_MODULE);
}
Self::Type(index) => {
bytes.extend(encoders::u32(*index));
bytes.push(ALIAS_KIND_OUTER_TYPE);
}
}
}
}
#[derive(Debug, Clone, Default)]
pub struct InstanceType {
bytes: Vec<u8>,
num_added: u32,
}
impl InstanceType {
pub fn new() -> Self {
Self::default()
}
#[must_use = "the encoder must be used to encode the type"]
pub fn ty(&mut self) -> TypeEncoder {
self.bytes.push(INSTANCE_TYPEDEF_TYPE);
self.num_added += 1;
TypeEncoder(&mut self.bytes)
}
pub fn alias_outer_module(&mut self, count: u32, index: OuterAliasIndex) -> &mut Self {
self.bytes.push(INSTANCE_TYPEDEF_ALIAS);
self.bytes.push(ALIAS_KIND_OUTER);
self.bytes.extend(encoders::u32(count));
index.encode(&mut self.bytes);
self.num_added += 1;
self
}
pub fn export(&mut self, name: &str, ty: TypeRef) -> &mut Self {
self.bytes.push(INSTANCE_TYPEDEF_EXPORT);
self.bytes.extend(encoders::str(name));
ty.encode(&mut self.bytes);
self.num_added += 1;
self
}
pub(crate) fn encode(&self, bytes: &mut Vec<u8>) {
bytes.extend(encoders::u32(self.num_added));
bytes.extend(self.bytes.iter().copied());
}
}
#[derive(Debug, Clone, Default)]
pub struct ModuleType {
bytes: Vec<u8>,
num_added: u32,
}
impl ModuleType {
pub fn new() -> Self {
Self::default()
}
#[must_use = "the encoder must be used to encode the type"]
pub fn ty(&mut self) -> TypeEncoder {
self.bytes.push(MODULE_TYPEDEF_TYPE);
self.num_added += 1;
TypeEncoder(&mut self.bytes)
}
pub fn alias_outer_module(&mut self, count: u32, index: OuterAliasIndex) -> &mut Self {
self.bytes.push(MODULE_TYPEDEF_ALIAS);
self.bytes.push(ALIAS_KIND_OUTER_MODULE);
self.bytes.extend(encoders::u32(count));
index.encode(&mut self.bytes);
self.num_added += 1;
self
}
pub fn export(&mut self, name: &str, ty: TypeRef) -> &mut Self {
self.bytes.push(MODULE_TYPEDEF_EXPORT);
self.bytes.extend(encoders::str(name));
ty.encode(&mut self.bytes);
self.num_added += 1;
self
}
pub fn import(&mut self, name: &str, ty: TypeRef) -> &mut Self {
self.bytes.push(MODULE_TYPEDEF_IMPORT);
self.bytes.extend(encoders::str(name));
ty.encode(&mut self.bytes);
self.num_added += 1;
self
}
pub(crate) fn encode(&self, bytes: &mut Vec<u8>) {
bytes.extend(encoders::u32(self.num_added));
bytes.extend(self.bytes.iter().copied());
}
}
#[derive(Debug)]
pub struct TypeEncoder<'a>(&'a mut Vec<u8>);
impl<'a> TypeEncoder<'a> {
pub fn instance(self, ty: &InstanceType) {
self.0.push(TYPE_INSTANCE);
ty.encode(self.0);
}
pub fn module(self, ty: &ModuleType) {
self.0.push(TYPE_MODULE);
ty.encode(self.0);
}
pub fn function(self, params: &[ValType], results: &[ValType]) {
self.0.push(TYPE_FUNCTION);
self.0
.extend(encoders::u32(u32::try_from(params.len()).unwrap()));
self.0.extend(params.iter().map(|p| u8::from(*p)));
self.0
.extend(encoders::u32(u32::try_from(results.len()).unwrap()));
self.0.extend(results.iter().map(|r| u8::from(*r)));
}
pub fn adapter_function(self, params: &[(&str, InterfaceType)], results: &[InterfaceType]) {
self.0.push(TYPE_ADAPTER_FUNCTION);
self.0
.extend(encoders::u32(u32::try_from(params.len()).unwrap()));
for (name, param) in params {
self.0.extend(encoders::str(name));
param.encode(self.0);
}
self.0
.extend(encoders::u32(u32::try_from(results.len()).unwrap()));
for result in results {
result.encode(self.0);
}
}
#[must_use = "the encoder must be used to encode the type"]
pub fn compound(self) -> CompoundTypeEncoder<'a> {
CompoundTypeEncoder(self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InterfaceType {
Bool,
S8,
U8,
S16,
U16,
S32,
U32,
S64,
U64,
F32,
F64,
Char,
String,
Compound(u32),
}
impl InterfaceType {
pub(crate) fn encode(&self, bytes: &mut Vec<u8>) {
match self {
Self::Bool => bytes.push(INTERFACE_TYPE_BOOL),
Self::S8 => bytes.push(INTERFACE_TYPE_S8),
Self::U8 => bytes.push(INTERFACE_TYPE_U8),
Self::S16 => bytes.push(INTERFACE_TYPE_S16),
Self::U16 => bytes.push(INTERFACE_TYPE_U16),
Self::S32 => bytes.push(INTERFACE_TYPE_S32),
Self::U32 => bytes.push(INTERFACE_TYPE_U32),
Self::S64 => bytes.push(INTERFACE_TYPE_S64),
Self::U64 => bytes.push(INTERFACE_TYPE_U64),
Self::F32 => bytes.push(INTERFACE_TYPE_F32),
Self::F64 => bytes.push(INTERFACE_TYPE_F64),
Self::Char => bytes.push(INTERFACE_TYPE_CHAR),
Self::String => bytes.push(INTERFACE_TYPE_STRING),
Self::Compound(index) => bytes.extend(encoders::u32(*index)),
}
}
}
#[derive(Debug)]
pub struct CompoundTypeEncoder<'a>(&'a mut Vec<u8>);
impl CompoundTypeEncoder<'_> {
pub fn list(self, ty: InterfaceType) {
self.0.push(COMPOUND_INTERFACE_TYPE_LIST);
ty.encode(self.0);
}
pub fn record(self, fields: &[(&str, InterfaceType)]) {
self.0.push(COMPOUND_INTERFACE_TYPE_RECORD);
self.0
.extend(encoders::u32(fields.len().try_into().unwrap()));
for (name, ty) in fields {
self.0.extend(encoders::str(name));
ty.encode(self.0);
}
}
pub fn variant(self, cases: &[(&str, Option<InterfaceType>)]) {
self.0.push(COMPOUND_INTERFACE_TYPE_VARIANT);
self.0
.extend(encoders::u32(cases.len().try_into().unwrap()));
for (name, ty) in cases {
self.0.extend(encoders::str(name));
if let Some(ty) = ty {
self.0.push(0x01);
ty.encode(self.0);
} else {
self.0.push(0x00);
}
}
}
pub fn tuple(self, types: &[InterfaceType]) {
self.0.push(COMPOUND_INTERFACE_TYPE_TUPLE);
self.0
.extend(encoders::u32(types.len().try_into().unwrap()));
for ty in types {
ty.encode(self.0);
}
}
pub fn flags(self, names: &[&str]) {
self.0.push(COMPOUND_INTERFACE_TYPE_FLAGS);
self.0
.extend(encoders::u32(names.len().try_into().unwrap()));
for name in names {
self.0.extend(encoders::str(name));
}
}
pub fn enum_type(self, tags: &[&str]) {
self.0.push(COMPOUND_INTERFACE_TYPE_ENUM);
self.0.extend(encoders::u32(tags.len().try_into().unwrap()));
for tag in tags {
self.0.extend(encoders::str(tag));
}
}
pub fn union(self, types: &[InterfaceType]) {
self.0.push(COMPOUND_INTERFACE_TYPE_UNION);
self.0
.extend(encoders::u32(types.len().try_into().unwrap()));
for ty in types {
ty.encode(self.0);
}
}
pub fn optional(self, ty: InterfaceType) {
self.0.push(COMPOUND_INTERFACE_TYPE_OPTIONAL);
ty.encode(self.0);
}
pub fn expected(self, ok: Option<InterfaceType>, error: Option<InterfaceType>) {
self.0.push(COMPOUND_INTERFACE_TYPE_EXPECTED);
if let Some(ok) = ok {
self.0.push(0x01);
ok.encode(self.0);
} else {
self.0.push(0x00);
}
if let Some(error) = error {
self.0.push(0x01);
error.encode(self.0);
} else {
self.0.push(0x00);
}
}
pub fn named(self, name: &str, ty: InterfaceType) {
self.0.push(COMPOUND_INTERFACE_TYPE_NAMED);
self.0.extend(encoders::str(name));
ty.encode(self.0);
}
}
#[derive(Clone, Debug, Default)]
pub struct TypeSection {
bytes: Vec<u8>,
num_added: u32,
}
impl TypeSection {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> u32 {
self.num_added
}
pub fn is_empty(&self) -> bool {
self.num_added == 0
}
pub fn instance(&mut self, ty: &InstanceType) -> &mut Self {
let encoder = TypeEncoder(&mut self.bytes);
encoder.instance(ty);
self.num_added += 1;
self
}
pub fn module(&mut self, ty: &ModuleType) -> &mut Self {
let encoder = TypeEncoder(&mut self.bytes);
encoder.module(ty);
self.num_added += 1;
self
}
pub fn function(&mut self, params: &[ValType], results: &[ValType]) -> &mut Self {
let encoder = TypeEncoder(&mut self.bytes);
encoder.function(params, results);
self.num_added += 1;
self
}
pub fn adapter_function(
&mut self,
params: &[(&str, InterfaceType)],
results: &[InterfaceType],
) -> &mut Self {
let encoder = TypeEncoder(&mut self.bytes);
encoder.adapter_function(params, results);
self.num_added += 1;
self
}
#[must_use = "the encoder must be used to encode the type"]
pub fn compound(&mut self) -> CompoundTypeEncoder<'_> {
let encoder = CompoundTypeEncoder(&mut self.bytes);
self.num_added += 1;
encoder
}
}
impl ComponentSection for TypeSection {
fn id(&self) -> u8 {
SectionId::Type.into()
}
fn encode<S>(&self, sink: &mut S)
where
S: Extend<u8>,
{
let num_added = encoders::u32(self.num_added);
let n = num_added.len();
sink.extend(
encoders::u32(u32::try_from(n + self.bytes.len()).unwrap())
.chain(num_added)
.chain(self.bytes.iter().copied()),
);
}
}