use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
use std::sync::Arc;
use wasmer_compiler::{CompileError, Target};
use wasmer_types::{FunctionType, FunctionTypeRef};
use wasmer_vm::{Artifact, Tunables, VMCallerCheckedAnyfunc, VMFuncRef, VMSharedSignatureIndex};
mod private {
pub struct Internal(pub(super) ());
}
pub trait Engine {
fn target(&self) -> &Target;
fn register_signature(&self, func_type: FunctionTypeRef<'_>) -> VMSharedSignatureIndex;
fn register_function_metadata(&self, func_data: VMCallerCheckedAnyfunc) -> VMFuncRef;
fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FunctionType>;
fn validate(&self, binary: &[u8]) -> Result<(), CompileError>;
fn compile(
&self,
binary: &[u8],
tunables: &dyn Tunables,
) -> Result<Box<dyn crate::Executable>, CompileError>;
fn load(&self, executable: &(dyn crate::Executable))
-> Result<Arc<dyn Artifact>, CompileError>;
fn id(&self) -> &EngineId;
fn cloned(&self) -> Arc<dyn Engine + Send + Sync>;
#[doc(hidden)]
fn type_id(&self, _: private::Internal) -> std::any::TypeId
where
Self: 'static,
{
std::any::TypeId::of::<Self>()
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct EngineId {
id: usize,
}
impl EngineId {
pub fn id(&self) -> String {
format!("{}", &self.id)
}
}
impl Clone for EngineId {
fn clone(&self) -> Self {
Self::default()
}
}
impl Default for EngineId {
fn default() -> Self {
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
Self {
id: NEXT_ID.fetch_add(1, SeqCst),
}
}
}
impl dyn Engine {
pub fn downcast_ref<T: Engine + 'static>(&self) -> Option<&T> {
if std::any::TypeId::of::<T>() == self.type_id(private::Internal(())) {
unsafe { Some(&*(self as *const dyn Engine as *const T)) }
} else {
None
}
}
}