use wasm_encoder::ValType;
pub(crate) struct DispatchIndices {
pub ty: u32,
pub func: u32,
}
impl DispatchIndices {
pub fn new() -> Self {
Self { ty: 0, func: 0 }
}
pub fn alloc_ty(&mut self) -> u32 {
let idx = self.ty;
self.ty += 1;
idx
}
pub fn alloc_func(&mut self) -> u32 {
let idx = self.func;
self.func += 1;
idx
}
}
pub(crate) struct LocalsBuilder {
base: u32,
locals: Vec<ValType>,
}
impl LocalsBuilder {
pub fn new(param_count: u32) -> Self {
Self {
base: param_count,
locals: Vec::new(),
}
}
pub fn alloc_local(&mut self, ty: ValType) -> u32 {
let idx = self.base + self.locals.len() as u32;
self.locals.push(ty);
idx
}
pub fn freeze(self) -> FrozenLocals {
FrozenLocals {
locals: self.locals,
}
}
}
pub(crate) struct FrozenLocals {
pub locals: Vec<ValType>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn locals_builder_allocates_contiguous_from_base() {
let mut idx = LocalsBuilder::new(3);
assert_eq!(idx.alloc_local(ValType::I32), 3);
assert_eq!(idx.alloc_local(ValType::I64), 4);
assert_eq!(idx.alloc_local(ValType::I32), 5);
assert_eq!(
idx.freeze().locals,
vec![ValType::I32, ValType::I64, ValType::I32]
);
}
#[test]
fn locals_builder_zero_params_starts_at_zero() {
let mut idx = LocalsBuilder::new(0);
assert_eq!(idx.alloc_local(ValType::I32), 0);
assert_eq!(idx.alloc_local(ValType::F64), 1);
}
#[test]
fn dispatch_indices_track_ty_and_func_independently() {
let mut idx = DispatchIndices::new();
assert_eq!(idx.alloc_ty(), 0);
assert_eq!(idx.alloc_func(), 0);
assert_eq!(idx.alloc_ty(), 1);
assert_eq!(idx.alloc_func(), 1);
}
}