1 | use std::ops::Deref; |
2 | use std::ptr; |
3 | |
4 | use super::{check_status, Value}; |
5 | use crate::{bindgen_runtime::ToNapiValue, sys, Env, Result}; |
6 | |
7 | pub struct Ref<T> { |
8 | pub(crate) raw_ref: sys::napi_ref, |
9 | pub(crate) count: u32, |
10 | pub(crate) inner: T, |
11 | } |
12 | |
13 | #[allow (clippy::non_send_fields_in_send_ty)] |
14 | unsafe impl<T> Send for Ref<T> {} |
15 | unsafe impl<T> Sync for Ref<T> {} |
16 | |
17 | impl<T> Ref<T> { |
18 | pub(crate) fn new(js_value: Value, ref_count: u32, inner: T) -> Result<Ref<T>> { |
19 | let mut raw_ref = ptr::null_mut(); |
20 | assert_ne!(ref_count, 0, "Initial `ref_count` must be > 0" ); |
21 | check_status!(unsafe { |
22 | sys::napi_create_reference(js_value.env, js_value.value, ref_count, &mut raw_ref) |
23 | })?; |
24 | Ok(Ref { |
25 | raw_ref, |
26 | count: ref_count, |
27 | inner, |
28 | }) |
29 | } |
30 | |
31 | pub fn reference(&mut self, env: &Env) -> Result<u32> { |
32 | check_status!(unsafe { sys::napi_reference_ref(env.0, self.raw_ref, &mut self.count) })?; |
33 | Ok(self.count) |
34 | } |
35 | |
36 | pub fn unref(&mut self, env: Env) -> Result<u32> { |
37 | check_status!(unsafe { sys::napi_reference_unref(env.0, self.raw_ref, &mut self.count) })?; |
38 | |
39 | if self.count == 0 { |
40 | check_status!(unsafe { sys::napi_delete_reference(env.0, self.raw_ref) })?; |
41 | } |
42 | Ok(self.count) |
43 | } |
44 | } |
45 | |
46 | impl<T> Deref for Ref<T> { |
47 | type Target = T; |
48 | |
49 | fn deref(&self) -> &T { |
50 | &self.inner |
51 | } |
52 | } |
53 | |
54 | #[cfg (debug_assertions)] |
55 | impl<T> Drop for Ref<T> { |
56 | fn drop(&mut self) { |
57 | debug_assert_eq!( |
58 | self.count, 0, |
59 | "Ref count is not equal to 0 while dropping Ref, potential memory leak" |
60 | ); |
61 | } |
62 | } |
63 | |
64 | impl<T: 'static> ToNapiValue for Ref<T> { |
65 | unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> { |
66 | let mut result: *mut napi_value__ = ptr::null_mut(); |
67 | check_status!( |
68 | unsafe { sys::napi_get_reference_value(env, val.raw_ref, &mut result) }, |
69 | "Failed to get reference value" |
70 | )?; |
71 | Ok(result) |
72 | } |
73 | } |
74 | |