napi/js_values/
unknown.rs1use std::ptr;
2
3use crate::{
4 bindgen_runtime::{Env, FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue},
5 check_status, sys, type_of, JsValue, Result, Value, ValueType,
6};
7
8#[derive(Clone, Copy)]
9pub struct Unknown<'env>(
11 pub(crate) Value,
12 pub(crate) std::marker::PhantomData<&'env ()>,
13);
14
15impl<'env> JsValue<'env> for Unknown<'env> {
16 fn value(&self) -> Value {
17 self.0
18 }
19}
20
21impl TypeName for Unknown<'_> {
22 fn type_name() -> &'static str {
23 "unknown"
24 }
25
26 fn value_type() -> ValueType {
27 ValueType::Unknown
28 }
29}
30
31impl ValidateNapiValue for Unknown<'_> {
32 unsafe fn validate(
33 _env: napi_sys::napi_env,
34 _napi_val: napi_sys::napi_value,
35 ) -> Result<sys::napi_value> {
36 Ok(ptr::null_mut())
37 }
38}
39
40impl FromNapiValue for Unknown<'_> {
41 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
42 Ok(Unknown(
43 Value {
44 env,
45 value: napi_val,
46 value_type: ValueType::Unknown,
47 },
48 std::marker::PhantomData,
49 ))
50 }
51}
52
53impl Unknown<'_> {
54 pub fn get_type(&self) -> Result<ValueType> {
55 type_of!(self.0.env, self.0.value)
56 }
57
58 pub unsafe fn cast<V>(&self) -> Result<V>
64 where
65 V: FromNapiValue,
66 {
67 unsafe { V::from_napi_value(self.0.env, self.0.value) }
68 }
69
70 pub unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> Self {
74 Unknown(
75 Value {
76 env,
77 value,
78 value_type: ValueType::Unknown,
79 },
80 std::marker::PhantomData,
81 )
82 }
83
84 pub fn create_ref(&self) -> Result<UnknownRef> {
86 let mut ref_ = ptr::null_mut();
87 check_status!(
88 unsafe { sys::napi_create_reference(self.0.env, self.0.value, 1, &mut ref_) },
89 "Failed to create reference"
90 )?;
91 Ok(UnknownRef { inner: ref_ })
92 }
93}
94
95pub struct UnknownRef<const LEAK_CHECK: bool = true> {
101 pub(crate) inner: sys::napi_ref,
102}
103
104unsafe impl<const LEAK_CHECK: bool> Send for UnknownRef<LEAK_CHECK> {}
105
106impl<const LEAK_CHECK: bool> Drop for UnknownRef<LEAK_CHECK> {
107 fn drop(&mut self) {
108 if LEAK_CHECK && !self.inner.is_null() {
109 eprintln!("ObjectRef is not unref, it considered as a memory leak");
110 }
111 }
112}
113
114impl<const LEAK_CHECK: bool> UnknownRef<LEAK_CHECK> {
115 pub fn get_value<'env>(&self, env: &'env Env) -> Result<Unknown<'env>> {
117 let mut result = ptr::null_mut();
118 check_status!(
119 unsafe { sys::napi_get_reference_value(env.0, self.inner, &mut result) },
120 "Failed to get reference value"
121 )?;
122 Ok(unsafe { Unknown::from_raw_unchecked(env.0, result) })
123 }
124
125 pub fn unref(mut self, env: &Env) -> Result<()> {
127 check_status!(
128 unsafe { sys::napi_reference_unref(env.0, self.inner, &mut 0) },
129 "unref Ref failed"
130 )?;
131 check_status!(
132 unsafe { sys::napi_delete_reference(env.0, self.inner) },
133 "delete Ref failed"
134 )?;
135 self.inner = ptr::null_mut();
136 Ok(())
137 }
138}
139
140impl<const LEAK_CHECK: bool> FromNapiValue for UnknownRef<LEAK_CHECK> {
141 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
142 let mut ref_ = ptr::null_mut();
143 check_status!(
144 unsafe { sys::napi_create_reference(env, napi_val, 1, &mut ref_) },
145 "Failed to create reference"
146 )?;
147 Ok(Self { inner: ref_ })
148 }
149}
150
151impl<const LEAK_CHECK: bool> ToNapiValue for &UnknownRef<LEAK_CHECK> {
152 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
153 let mut result = ptr::null_mut();
154 check_status!(
155 unsafe { sys::napi_get_reference_value(env, val.inner, &mut result) },
156 "Failed to get reference value"
157 )?;
158 Ok(result)
159 }
160}
161
162impl<const LEAK_CHECK: bool> ToNapiValue for UnknownRef<LEAK_CHECK> {
163 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
164 let mut result = ptr::null_mut();
165 check_status!(
166 unsafe { sys::napi_get_reference_value(env, val.inner, &mut result) },
167 "Failed to get reference value"
168 )?;
169 check_status!(
170 unsafe { sys::napi_delete_reference(env, val.inner) },
171 "Failed to delete reference"
172 )?;
173 Ok(result)
174 }
175}