napi/js_values/
value_ref.rs1use std::{marker::PhantomData, ptr};
2
3use crate::{
4 bindgen_runtime::{FromNapiMutRef, FromNapiValue, ToNapiValue},
5 check_status, sys, Env, JsValue, Result,
6};
7
8pub struct Ref<T> {
9 pub(crate) raw_ref: sys::napi_ref,
10 pub(crate) _phantom: PhantomData<T>,
11 pub(crate) taken: bool,
12}
13
14#[allow(clippy::non_send_fields_in_send_ty)]
15unsafe impl<T> Send for Ref<T> {}
16unsafe impl<T> Sync for Ref<T> {}
17
18impl<'env, T: JsValue<'env>> Ref<T> {
19 pub fn new(env: &Env, value: &T) -> Result<Ref<T>> {
20 let mut raw_ref = ptr::null_mut();
21 check_status!(
22 unsafe { sys::napi_create_reference(env.0, value.raw(), 1, &mut raw_ref) },
23 "Create napi_ref from {} failed",
24 std::any::type_name::<T>()
25 )?;
26 Ok(Ref {
27 raw_ref,
28 taken: false,
29 _phantom: PhantomData,
30 })
31 }
32
33 pub fn unref(&mut self, env: &Env) -> Result<()> {
34 check_status!(
35 unsafe { sys::napi_reference_unref(env.0, self.raw_ref, &mut 0) },
36 "unref Ref failed"
37 )?;
38
39 check_status!(
40 unsafe { sys::napi_delete_reference(env.0, self.raw_ref) },
41 "delete Ref failed"
42 )?;
43 self.taken = true;
44 Ok(())
45 }
46}
47
48impl<T: FromNapiValue> Ref<T> {
49 pub fn get_value(&self, env: &Env) -> Result<T> {
51 if self.taken {
52 return Err(crate::Error::new(
53 crate::Status::InvalidArg,
54 "Ref value has been deleted",
55 ));
56 }
57 let mut result = ptr::null_mut();
58 check_status!(
59 unsafe { sys::napi_get_reference_value(env.0, self.raw_ref, &mut result) },
60 "Failed to get reference value"
61 )?;
62 unsafe { T::from_napi_value(env.0, result) }
63 }
64}
65
66impl<T: 'static + FromNapiMutRef> Ref<T> {
67 #[allow(clippy::mut_from_ref)]
69 pub fn get_value_mut(&self, env: &Env) -> Result<&mut T> {
70 let mut result = ptr::null_mut();
71 check_status!(
72 unsafe { sys::napi_get_reference_value(env.0, self.raw_ref, &mut result) },
73 "Failed to get reference value"
74 )?;
75 unsafe { T::from_napi_mut_ref(env.0, result) }
76 }
77}
78
79impl<'env, T: FromNapiValue + JsValue<'env>> FromNapiValue for Ref<T> {
80 unsafe fn from_napi_value(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
81 let val = T::from_napi_value(env, value)?;
82 Ref::new(&Env::from_raw(env), &val)
83 }
84}
85
86impl<T: 'static> ToNapiValue for Ref<T> {
87 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
88 let mut result = ptr::null_mut();
89 check_status!(
90 unsafe { sys::napi_get_reference_value(env, val.raw_ref, &mut result) },
91 "Failed to get reference value"
92 )?;
93 Ok(result)
94 }
95}