use crate::sys::{ExportError, Instance};
use thiserror::Error;
#[derive(Error, Debug)]
#[error("Host env initialization error: {0}")]
pub enum HostEnvInitError {
Export(ExportError),
}
impl From<ExportError> for HostEnvInitError {
fn from(other: ExportError) -> Self {
Self::Export(other)
}
}
pub trait WasmerEnv: Clone + Send + Sync {
fn init_with_instance(&mut self, _instance: &Instance) -> Result<(), HostEnvInitError> {
Ok(())
}
}
impl WasmerEnv for u8 {}
impl WasmerEnv for i8 {}
impl WasmerEnv for u16 {}
impl WasmerEnv for i16 {}
impl WasmerEnv for u32 {}
impl WasmerEnv for i32 {}
impl WasmerEnv for u64 {}
impl WasmerEnv for i64 {}
impl WasmerEnv for u128 {}
impl WasmerEnv for i128 {}
impl WasmerEnv for f32 {}
impl WasmerEnv for f64 {}
impl WasmerEnv for usize {}
impl WasmerEnv for isize {}
impl WasmerEnv for char {}
impl WasmerEnv for bool {}
impl WasmerEnv for String {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicBool {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI8 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU8 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI16 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU16 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI32 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicU32 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicI64 {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicUsize {}
impl<'a> WasmerEnv for &'a ::std::sync::atomic::AtomicIsize {}
impl<T: WasmerEnv> WasmerEnv for Box<T> {
fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> {
(&mut **self).init_with_instance(instance)
}
}
impl<T: WasmerEnv> WasmerEnv for ::std::sync::Arc<::std::sync::Mutex<T>> {
fn init_with_instance(&mut self, instance: &Instance) -> Result<(), HostEnvInitError> {
let mut guard = self.lock().unwrap();
guard.init_with_instance(instance)
}
}
pub struct LazyInit<T: Sized> {
data: std::mem::MaybeUninit<T>,
initialized: bool,
}
impl<T> LazyInit<T> {
pub fn new() -> Self {
Self {
data: std::mem::MaybeUninit::uninit(),
initialized: false,
}
}
pub unsafe fn get_unchecked(&self) -> &T {
&*self.data.as_ptr()
}
pub fn get_ref(&self) -> Option<&T> {
if !self.initialized {
None
} else {
Some(unsafe { self.get_unchecked() })
}
}
pub fn initialize(&mut self, value: T) -> bool {
if self.initialized {
return false;
}
unsafe {
self.data.as_mut_ptr().write(value);
}
self.initialized = true;
true
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for LazyInit<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("LazyInit")
.field("data", &self.get_ref())
.finish()
}
}
impl<T: Clone> Clone for LazyInit<T> {
fn clone(&self) -> Self {
if let Some(inner) = self.get_ref() {
Self {
data: std::mem::MaybeUninit::new(inner.clone()),
initialized: true,
}
} else {
Self {
data: std::mem::MaybeUninit::uninit(),
initialized: false,
}
}
}
}
impl<T> Drop for LazyInit<T> {
fn drop(&mut self) {
if self.initialized {
unsafe {
let ptr = self.data.as_mut_ptr();
std::ptr::drop_in_place(ptr);
};
}
}
}
impl<T> Default for LazyInit<T> {
fn default() -> Self {
Self::new()
}
}
unsafe impl<T: Send> Send for LazyInit<T> {}