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