use std::{marker::PhantomData, ptr};
use crate::{
bindgen_prelude::{
sys, External, ExternalRef, FromNapiValue, Result, TypeName, ValidateNapiValue,
},
check_status, JsValue, Value, ValueType,
};
pub struct JsExternal<'env>(pub(crate) Value, PhantomData<&'env ()>);
impl<'env> TypeName for JsExternal<'env> {
fn type_name() -> &'static str {
"External"
}
fn value_type() -> ValueType {
ValueType::External
}
}
impl<'env> ValidateNapiValue for JsExternal<'env> {}
impl<'env> FromNapiValue for JsExternal<'env> {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
Ok(Self(
Value {
env,
value: napi_val,
value_type: ValueType::External,
},
PhantomData,
))
}
}
impl<'env> JsValue<'env> for JsExternal<'env> {
fn value(&self) -> Value {
self.0
}
}
impl<'env> JsExternal<'env> {
pub fn get_value<T: 'static>(&self) -> Result<&T> {
self.get_static_value::<T>().map(|ext| ext.as_ref())
}
pub unsafe fn get_value_mut<T: 'static>(&mut self) -> Result<&mut T> {
let mut unknown_tagged_object = ptr::null_mut();
check_status!(
unsafe { sys::napi_get_value_external(self.0.env, self.0.value, &mut unknown_tagged_object) },
"Failed to get external value"
)?;
unsafe { External::inner_from_napi_value_mut(self.0.env, self.0.value, unknown_tagged_object) }
}
pub fn create_ref<T: 'static>(&self) -> Result<ExternalRef<T>> {
unsafe { ExternalRef::from_napi_value(self.0.env, self.0.value) }
}
#[inline]
fn get_static_value<T: 'static>(&self) -> Result<&'static External<T>> {
let mut unknown_tagged_object = ptr::null_mut();
check_status!(
unsafe { sys::napi_get_value_external(self.0.env, self.0.value, &mut unknown_tagged_object) },
"Failed to get external value"
)?;
unsafe { External::from_napi_value_impl(self.0.env, self.0.value, unknown_tagged_object) }
}
}