use core::cmp::Ordering; use core::fmt::{self, Debug, Display}; use core::mem; use core::ops::{Deref, DerefMut}; use core::ptr; use std::marker::PhantomData; use js_sys::Uint8Array; use wasm_bindgen::JsValue; /// A mutable Wasm-memory location. pub struct WasmCell<'a, T: ?Sized> { pub(crate) memory: Uint8Array, phantom: &'a PhantomData, } unsafe impl Send for WasmCell<'_, T> where T: Send {} unsafe impl Sync for WasmCell<'_, T> {} impl<'a, T: Copy> Clone for WasmCell<'a, T> { #[inline] fn clone(&self) -> WasmCell<'a, T> { WasmCell { memory: self.memory.clone(), phantom: &PhantomData, } } } impl PartialEq for WasmCell<'_, T> { #[inline] fn eq(&self, other: &WasmCell) -> bool { true } } impl Eq for WasmCell<'_, T> {} impl PartialOrd for WasmCell<'_, T> { #[inline] fn partial_cmp(&self, other: &WasmCell) -> Option { self.get().partial_cmp(&other.get()) } #[inline] fn lt(&self, other: &WasmCell) -> bool { self.get() < other.get() } #[inline] fn le(&self, other: &WasmCell) -> bool { self.get() <= other.get() } #[inline] fn gt(&self, other: &WasmCell) -> bool { self.get() > other.get() } #[inline] fn ge(&self, other: &WasmCell) -> bool { self.get() >= other.get() } } impl Ord for WasmCell<'_, T> { #[inline] fn cmp(&self, other: &WasmCell) -> Ordering { self.get().cmp(&other.get()) } } impl<'a, T> WasmCell<'a, T> { /// Creates a new `WasmCell` containing the given value. /// /// # Examples /// /// ``` /// use std::cell::Cell; /// use wasmer::WasmCell; /// /// let cell = Cell::new(5); /// let wasm_cell = WasmCell::new(&cell); /// ``` #[inline] pub const fn new(memory: Uint8Array) -> WasmCell<'a, T> { WasmCell { memory, phantom: &PhantomData, } } } impl<'a, T: Copy> WasmCell<'a, T> { /// Returns a copy of the contained value. /// /// # Examples /// /// ``` /// use std::cell::Cell; /// use wasmer::WasmCell; /// /// let cell = Cell::new(5); /// let wasm_cell = WasmCell::new(&cell); /// let five = wasm_cell.get(); /// ``` #[inline] pub fn get(&self) -> T { let vec = self.memory.to_vec(); unsafe { *(vec.as_ptr() as *const T) } } } impl Debug for WasmCell<'_, T> { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.get().fmt(f) } } impl WasmCell<'_, T> { /// Sets the contained value. /// /// # Examples /// /// ``` /// use std::cell::Cell; /// use wasmer::WasmCell; /// /// let cell = Cell::new(5); /// let wasm_cell = WasmCell::new(&cell); /// wasm_cell.set(10); /// assert_eq!(cell.get(), 10); /// ``` #[inline] pub fn set(&self, val: T) { let size = std::mem::size_of::(); let ptr = &val as *const T as *const u8; let slice = unsafe { std::slice::from_raw_parts(ptr, size) }; self.memory.copy_from(slice); } }