use super::{Field, Input};
use crate::schema::FieldTag;
use std::collections::HashMap;
use wasm_encoder::{FuncType, HeapType, RefType, StorageType, ValType};
pub(super) fn schema_index(input: &Input, schema: u32) -> u32 {
input.types + schema
}
pub(super) fn storage_type(input: &Input, field: &Field) -> StorageType {
match field.tag {
FieldTag::I8 => StorageType::I8,
FieldTag::I16 => StorageType::I16,
FieldTag::I32
| FieldTag::I64
| FieldTag::F32
| FieldTag::F64
| FieldTag::Bool
| FieldTag::ExternRef
| FieldTag::Ref
| FieldTag::NullableRef
| FieldTag::Array
| FieldTag::NullableArray => StorageType::Val(value_type(input, field)),
}
}
pub(super) fn value_type(input: &Input, field: &Field) -> ValType {
match field.tag {
FieldTag::I8 | FieldTag::I16 | FieldTag::I32 | FieldTag::Bool => ValType::I32,
FieldTag::I64 => ValType::I64,
FieldTag::F32 => ValType::F32,
FieldTag::F64 => ValType::F64,
FieldTag::ExternRef => ValType::EXTERNREF,
FieldTag::Ref | FieldTag::NullableRef | FieldTag::Array | FieldTag::NullableArray => {
ValType::Ref(RefType {
nullable: matches!(field.tag, FieldTag::NullableRef | FieldTag::NullableArray),
heap_type: HeapType::Concrete(schema_index(
input,
field.target.expect("reference field target"),
)),
})
}
}
}
pub(super) struct FunctionTypes {
first: u32,
signatures: Vec<FuncType>,
indices: HashMap<FuncType, u32>,
}
impl FunctionTypes {
pub fn new(first: u32) -> Self {
Self {
first,
signatures: Vec::new(),
indices: HashMap::new(),
}
}
pub fn intern(
&mut self,
params: impl IntoIterator<Item = ValType>,
results: impl IntoIterator<Item = ValType>,
) -> u32 {
let signature = FuncType::new(params, results);
if let Some(&index) = self.indices.get(&signature) {
return index;
}
let index = self.first + self.signatures.len() as u32;
self.indices.insert(signature.clone(), index);
self.signatures.push(signature);
index
}
pub fn finish(self) -> Vec<FuncType> {
self.signatures
}
}