use std::ops::Deref; use std::ptr; use super::{check_status, Value}; use crate::{sys, Env, Result}; pub struct Ref { pub(crate) raw_ref: sys::napi_ref, count: u32, inner: T, } unsafe impl Send for Ref {} unsafe impl Sync for Ref {} impl Ref { pub(crate) fn new(js_value: Value, ref_count: u32, inner: T) -> Result> { let mut raw_ref = ptr::null_mut(); let initial_ref_count = 1; check_status(unsafe { sys::napi_create_reference( js_value.env, js_value.value, initial_ref_count, &mut raw_ref, ) })?; Ok(Ref { raw_ref, count: ref_count, inner, }) } pub fn reference(&mut self, env: &Env) -> Result { check_status(unsafe { sys::napi_reference_ref(env.0, self.raw_ref, &mut self.count) })?; Ok(self.count) } #[must_use] pub fn unref(mut self, env: Env) -> Result { check_status(unsafe { sys::napi_reference_unref(env.0, self.raw_ref, &mut self.count) })?; if self.count == 0 { check_status(unsafe { sys::napi_delete_reference(env.0, self.raw_ref) })?; } Ok(self.count) } } impl Deref for Ref { type Target = T; fn deref(&self) -> &T { &self.inner } } #[cfg(debug_assertions)] impl Drop for Ref { fn drop(&mut self) { debug_assert_eq!( self.count, 0, "Ref count is not equal to 0 while dropping Ref, potential memory leak" ); } }