1use std::mem::MaybeUninit;
2
3use super::{
4 bindings as napi,
5 debug_send_wrapper::DebugSendWrapper,
6 raw::{Env, Local},
7};
8
9extern "C" fn finalize_external<T: 'static>(
11 env: Env,
12 data: *mut std::ffi::c_void,
14 hint: *mut std::ffi::c_void,
17) {
18 unsafe {
19 let data = Box::<DebugSendWrapper<T>>::from_raw(data as *mut _);
20 let finalizer: fn(Env, T) = std::mem::transmute(hint as *const ());
21
22 finalizer(env, data.take());
23 }
24}
25
26pub unsafe fn deref<T: 'static>(env: Env, local: Local) -> Option<*const T> {
32 let mut result = MaybeUninit::uninit();
33 napi::typeof_value(env, local, result.as_mut_ptr()).unwrap();
34
35 let result = result.assume_init();
36
37 if result != napi::ValueType::External {
39 return None;
40 }
41
42 #[cfg(feature = "napi-8")]
45 if !super::tag::check_object_type_tag(env, local, &crate::MODULE_TAG) {
47 return None;
48 }
49
50 let mut result = MaybeUninit::uninit();
51 napi::get_value_external(env, local, result.as_mut_ptr()).unwrap();
52
53 let v = result.assume_init();
54 let v = &**v.cast_const().cast::<DebugSendWrapper<T>>() as *const T;
55
56 Some(v)
57}
58
59pub unsafe fn create<T: 'static>(env: Env, v: T, finalizer: fn(Env, T)) -> Local {
61 let v = Box::new(DebugSendWrapper::new(v));
62 let mut result = MaybeUninit::uninit();
63
64 let status = napi::create_external(
65 env,
66 Box::into_raw(v) as *mut _,
67 Some(finalize_external::<T>),
68 finalizer as *const () as *mut _,
71 result.as_mut_ptr(),
72 );
73
74 status.unwrap();
77
78 let external = result.assume_init();
79
80 #[cfg(feature = "napi-8")]
81 super::tag::type_tag_object(env, external, &crate::MODULE_TAG);
83
84 external
85}