use std::any::Any; use std::cell::{self, RefCell}; use std::convert::TryFrom; use std::marker::PhantomData; use wasmtime::{ExternRef, Store}; /// Represents a piece of data located in the host environment. #[derive(Debug)] pub struct HostRef where T: 'static + Any, { externref: ExternRef, _phantom: PhantomData, } impl HostRef where T: 'static + Any, { /// Creates a new `HostRef` from `T`. pub fn new(store: &Store, item: T) -> HostRef { HostRef { externref: ExternRef::new(store, RefCell::new(item)), _phantom: PhantomData, } } /// Immutably borrows the wrapped data. /// /// # Panics /// /// Panics if the value is currently mutably borrowed. pub fn borrow(&self) -> cell::Ref { self.inner().borrow() } /// Mutably borrows the wrapped data. /// /// # Panics /// /// Panics if the `HostRef` is already borrowed. pub fn borrow_mut(&self) -> cell::RefMut { self.inner().borrow_mut() } /// Returns true if the two `HostRef`'s point to the same value (not just /// values that compare as equal). pub fn ptr_eq(&self, other: &HostRef) -> bool { self.externref.ptr_eq(&other.externref) } fn inner(&self) -> &RefCell { self.externref .data() .downcast_ref::>() .expect("`HostRef`s always wrap an `ExternRef` of `RefCell`") } } impl AsRef for HostRef { fn as_ref(&self) -> &ExternRef { &self.externref } } impl From> for ExternRef where T: 'static + Any, { fn from(host: HostRef) -> ExternRef { host.externref } } impl TryFrom for HostRef where T: 'static + Any, { type Error = ExternRef; fn try_from(externref: ExternRef) -> Result { if externref.data().is::>() { Ok(HostRef { externref, _phantom: PhantomData, }) } else { Err(externref) } } } impl Clone for HostRef { fn clone(&self) -> HostRef { HostRef { externref: self.externref.clone(), _phantom: PhantomData, } } }