use super::{ByteBuffer, SizeDescription};
use crate::{Result, ToJsValue};
use js_sys::{Array, Reflect};
use wasm_bindgen::JsValue;
pub trait Lower: SizeDescription {
fn to_js_args<M: WriteableMemory>(&self, args: &mut JsArgsWriter, memory: &M) -> Result<()>;
fn to_js_return<M: WriteableMemory>(&self, memory: &M) -> Result<JsValue>;
fn write_to<M: WriteableMemory>(&self, buffer: &mut ByteBuffer, memory: &M) -> Result<()>;
fn to_js_ptr_return<M: WriteableMemory>(&self, memory: &M) -> Result<JsValue> {
debug_assert!(Self::NUM_ARGS > 1);
let mut buffer = memory.allocate(Self::ALIGNMENT, Self::BYTE_SIZE)?;
self.write_to(&mut buffer, memory)?;
let addr = memory.flush(buffer) as u32;
Ok(addr.to_js_value())
}
}
pub trait WriteableMemory {
fn allocate(&self, align: usize, size: usize) -> Result<ByteBuffer>;
fn flush(&self, buffer: ByteBuffer) -> usize;
}
impl<T: WriteableMemory> WriteableMemory for &T {
fn allocate(&self, align: usize, size: usize) -> Result<ByteBuffer> {
T::allocate(self, align, size)
}
fn flush(&self, buffer: ByteBuffer) -> usize {
T::flush(self, buffer)
}
}
pub struct JsArgsWriter<'a> {
args: &'a Array,
index: u32,
}
impl<'a> JsArgsWriter<'a> {
pub fn new(args: &'a Array) -> Self {
Self { args, index: 0 }
}
pub fn push(&mut self, arg: &JsValue) {
Reflect::set_u32(self.args, self.index, arg).expect("args in an array");
self.index += 1;
}
pub fn skip(&mut self, num: usize) {
self.index += num as u32;
}
}