1use std::ptr;
2
3use crate::{
4 bindgen_runtime::{Env, FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue},
5 check_status, sys, JsValue, Result, Value, ValueType,
6};
7
8#[derive(Clone, Copy)]
9pub struct JsSymbol<'env>(
11 pub(crate) Value,
12 pub(crate) std::marker::PhantomData<&'env ()>,
13);
14
15impl TypeName for JsSymbol<'_> {
16 fn type_name() -> &'static str {
17 "symbol"
18 }
19
20 fn value_type() -> ValueType {
21 ValueType::Symbol
22 }
23}
24
25impl<'env> JsValue<'env> for JsSymbol<'env> {
26 fn value(&self) -> Value {
27 self.0
28 }
29}
30
31impl FromNapiValue for JsSymbol<'_> {
32 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
33 Ok(JsSymbol(
34 Value {
35 env,
36 value: napi_val,
37 value_type: ValueType::Symbol,
38 },
39 std::marker::PhantomData,
40 ))
41 }
42}
43
44impl ValidateNapiValue for JsSymbol<'_> {}
45
46impl JsSymbol<'_> {
47 pub fn create_ref<const LEAK_CHECK: bool>(&self) -> Result<SymbolRef<LEAK_CHECK>> {
49 let mut ref_ = ptr::null_mut();
50 check_status!(
51 unsafe { sys::napi_create_reference(self.0.env, self.0.value, 1, &mut ref_) },
52 "Failed to create reference"
53 )?;
54 Ok(SymbolRef { inner: ref_ })
55 }
56}
57
58pub struct SymbolRef<const LEAK_CHECK: bool = true> {
64 pub(crate) inner: sys::napi_ref,
65}
66
67unsafe impl<const LEAK_CHECK: bool> Send for SymbolRef<LEAK_CHECK> {}
68
69impl<const LEAK_CHECK: bool> Drop for SymbolRef<LEAK_CHECK> {
70 fn drop(&mut self) {
71 if LEAK_CHECK && !self.inner.is_null() {
72 eprintln!("ObjectRef is not unref, it considered as a memory leak");
73 }
74 }
75}
76
77impl<const LEAK_CHECK: bool> SymbolRef<LEAK_CHECK> {
78 pub fn get_value<'env>(&self, env: &'env Env) -> Result<JsSymbol<'env>> {
80 let mut result = ptr::null_mut();
81 check_status!(
82 unsafe { sys::napi_get_reference_value(env.0, self.inner, &mut result) },
83 "Failed to get reference value"
84 )?;
85 unsafe { JsSymbol::from_napi_value(env.0, result) }
86 }
87
88 pub fn unref(mut self, env: &Env) -> Result<()> {
90 check_status!(
91 unsafe { sys::napi_delete_reference(env.0, self.inner) },
92 "delete Ref failed"
93 )?;
94 self.inner = ptr::null_mut();
95 Ok(())
96 }
97}
98
99impl<const LEAK_CHECK: bool> FromNapiValue for SymbolRef<LEAK_CHECK> {
100 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
101 let mut ref_ = ptr::null_mut();
102 check_status!(
103 unsafe { sys::napi_create_reference(env, napi_val, 1, &mut ref_) },
104 "Failed to create reference"
105 )?;
106 Ok(Self { inner: ref_ })
107 }
108}
109
110impl<const LEAK_CHECK: bool> ToNapiValue for &SymbolRef<LEAK_CHECK> {
111 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
112 let mut result = ptr::null_mut();
113 check_status!(
114 unsafe { sys::napi_get_reference_value(env, val.inner, &mut result) },
115 "Failed to get reference value"
116 )?;
117 Ok(result)
118 }
119}
120
121impl<const LEAK_CHECK: bool> ToNapiValue for SymbolRef<LEAK_CHECK> {
122 unsafe fn to_napi_value(env: sys::napi_env, mut val: Self) -> Result<sys::napi_value> {
123 let mut result = ptr::null_mut();
124 check_status!(
125 unsafe { sys::napi_get_reference_value(env, val.inner, &mut result) },
126 "Failed to get reference value"
127 )?;
128 check_status!(
129 unsafe { sys::napi_delete_reference(env, val.inner) },
130 "delete Ref failed"
131 )?;
132 val.inner = ptr::null_mut();
133 drop(val);
134 Ok(result)
135 }
136}