pub(crate) mod internal;
pub(crate) mod root;
use std::{
error::Error,
fmt::{self, Debug, Display},
marker::PhantomData,
mem,
ops::{Deref, DerefMut},
};
pub use self::root::Root;
use crate::{
context::Context,
handle::internal::{SuperType, TransparentNoCopyWrapper},
result::{JsResult, ResultExt},
sys,
types::Value,
};
#[derive(Debug)]
#[repr(transparent)]
pub struct Handle<'a, V: Value + 'a> {
value: <V as TransparentNoCopyWrapper>::Inner,
phantom: PhantomData<&'a V>,
}
impl<'a, V: Value> Clone for Handle<'a, V> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, V: Value> Copy for Handle<'a, V> {}
impl<'a, V: Value + 'a> Handle<'a, V> {
pub(crate) fn new_internal(value: V) -> Handle<'a, V> {
Handle {
value: value.into_inner(),
phantom: PhantomData,
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct DowncastError<F: Value, T: Value> {
phantom_from: PhantomData<F>,
phantom_to: PhantomData<T>,
}
impl<F: Value, T: Value> Debug for DowncastError<F, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "DowncastError")
}
}
impl<F: Value, T: Value> DowncastError<F, T> {
fn new() -> Self {
DowncastError {
phantom_from: PhantomData,
phantom_to: PhantomData,
}
}
}
impl<F: Value, T: Value> Display for DowncastError<F, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "failed to downcast {} to {}", F::name(), T::name())
}
}
impl<F: Value, T: Value> Error for DowncastError<F, T> {}
pub type DowncastResult<'a, F, T> = Result<Handle<'a, T>, DowncastError<F, T>>;
impl<'a, F: Value, T: Value> ResultExt<Handle<'a, T>> for DowncastResult<'a, F, T> {
fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, T> {
match self {
Ok(v) => Ok(v),
Err(e) => cx.throw_type_error(e.to_string()),
}
}
}
impl<'a, T: Value> Handle<'a, T> {
pub fn upcast<U: Value + SuperType<T>>(&self) -> Handle<'a, U> {
Handle::new_internal(SuperType::upcast_internal(self.deref()))
}
pub fn is_a<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> bool {
U::is_typeof(cx.cx_mut(), self.deref())
}
pub fn downcast<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> DowncastResult<'a, T, U> {
match U::downcast(cx.cx_mut(), self.deref()) {
Some(v) => Ok(Handle::new_internal(v)),
None => Err(DowncastError::new()),
}
}
pub fn downcast_or_throw<'b, U: Value, C: Context<'b>>(&self, cx: &mut C) -> JsResult<'a, U> {
self.downcast(cx).or_throw(cx)
}
pub fn strict_equals<'b, U: Value, C: Context<'b>>(
&self,
cx: &mut C,
other: Handle<'b, U>,
) -> bool {
unsafe { sys::mem::strict_equals(cx.env().to_raw(), self.to_local(), other.to_local()) }
}
}
impl<'a, V: Value> Deref for Handle<'a, V> {
type Target = V;
fn deref(&self) -> &V {
unsafe { mem::transmute(&self.value) }
}
}
impl<'a, V: Value> DerefMut for Handle<'a, V> {
fn deref_mut(&mut self) -> &mut V {
unsafe { mem::transmute(&mut self.value) }
}
}