use std::ops::Deref;
use wasm_bindgen::prelude::*;
pub struct WasmBuffer {
data: Vec<u8>,
}
impl WasmBuffer {
pub fn with_capacity(capacity: usize) -> Self {
Self {
data: Vec::with_capacity(capacity),
}
}
pub fn from_slice(slice: &[u8]) -> Self {
Self {
data: slice.to_vec(),
}
}
pub fn from_vec(data: Vec<u8>) -> Self {
Self { data }
}
pub fn as_slice(&self) -> &[u8] {
&self.data
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
&mut self.data
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn clear(&mut self) {
self.data.clear();
}
pub fn shrink_to_fit(&mut self) {
self.data.shrink_to_fit();
}
pub fn into_vec(self) -> Vec<u8> {
self.data
}
}
impl Deref for WasmBuffer {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl Drop for WasmBuffer {
fn drop(&mut self) {
self.data.clear();
self.data.shrink_to_fit();
}
}
#[wasm_bindgen]
pub struct SharedImageBuffer {
buffer: WasmBuffer,
width: u32,
height: u32,
}
#[wasm_bindgen]
impl SharedImageBuffer {
#[wasm_bindgen(constructor)]
pub fn new(width: u32, height: u32) -> Self {
let size = (width * height * 4) as usize; Self {
buffer: WasmBuffer::with_capacity(size),
width,
height,
}
}
#[wasm_bindgen(getter)]
pub fn width(&self) -> u32 {
self.width
}
#[wasm_bindgen(getter)]
pub fn height(&self) -> u32 {
self.height
}
#[wasm_bindgen(js_name = bufferSize)]
pub fn buffer_size(&self) -> usize {
self.buffer.len()
}
#[wasm_bindgen(js_name = getBuffer)]
pub fn get_buffer(&self) -> js_sys::Uint8Array {
js_sys::Uint8Array::from(self.buffer.as_slice())
}
#[wasm_bindgen(js_name = setBuffer)]
pub fn set_buffer(&mut self, data: &js_sys::Uint8Array) {
self.buffer = WasmBuffer::from_vec(data.to_vec());
}
pub fn clear(&mut self) {
self.buffer.clear();
}
}
pub struct MemoryPool {
buffers: Vec<WasmBuffer>,
max_size: usize,
}
impl MemoryPool {
pub fn new(max_size: usize) -> Self {
Self {
buffers: Vec::with_capacity(max_size),
max_size,
}
}
pub fn acquire(&mut self, size: usize) -> WasmBuffer {
self.buffers
.pop()
.map(|mut buf| {
buf.clear();
buf
})
.unwrap_or_else(|| WasmBuffer::with_capacity(size))
}
pub fn release(&mut self, mut buffer: WasmBuffer) {
if self.buffers.len() < self.max_size {
buffer.clear();
self.buffers.push(buffer);
}
}
pub fn clear(&mut self) {
self.buffers.clear();
}
}
impl Default for MemoryPool {
fn default() -> Self {
Self::new(10)
}
}
#[wasm_bindgen(js_name = getMemoryStats)]
pub fn get_memory_stats() -> JsValue {
#[cfg(target_arch = "wasm32")]
{
use wasm_bindgen::JsValue;
let performance = web_sys::window().and_then(|w| w.performance());
if let Some(perf) = performance {
serde_wasm_bindgen::to_value(&serde_json::json!({
"available": true,
"timestamp": perf.now(),
}))
.unwrap_or(JsValue::NULL)
} else {
JsValue::NULL
}
}
#[cfg(not(target_arch = "wasm32"))]
JsValue::NULL
}
#[wasm_bindgen(js_name = forceGC)]
pub fn force_gc() {
}