1#![allow(ambiguous_glob_reexports)]
4
5#[cfg(any(
6 target_env = "msvc",
7 all(not(target_family = "wasm"), feature = "dyn-symbols")
8))]
9#[inline(never)]
10unsafe fn load_symbol(
11 host: &libloading::Library,
12 name: &'static [u8],
13) -> Option<*mut std::ffi::c_void> {
14 match unsafe { host.get::<unsafe extern "C" fn()>(name) } {
15 Ok(symbol) => unsafe { symbol.try_as_raw_ptr() },
16 Err(_) => None,
17 }
18}
19
20#[cfg(any(
21 target_env = "msvc",
22 all(not(target_family = "wasm"), feature = "dyn-symbols")
23))]
24macro_rules! generate {
25 (@stub_fn $name:ident($($param:ident: $ptype:ty,)*) -> napi_status) => {
26 unsafe extern "C" fn $name($(_: $ptype,)*) -> napi_status {
27 eprintln!("Node-API symbol {} has not been loaded", stringify!($name));
28 1
29 }
30 };
31 (@stub_fn $name:ident($($param:ident: $ptype:ty,)*) -> $rtype:ty) => {
32 unsafe extern "C" fn $name($(_: $ptype,)*) -> $rtype {
33 eprintln!("Node-API symbol {} has not been loaded", stringify!($name));
34 unsafe { std::mem::zeroed() }
35 }
36 };
37 (@stub_fn $name:ident($($param:ident: $ptype:ty,)*)) => {
38 unsafe extern "C" fn $name($(_: $ptype,)*) {
39 eprintln!("Node-API symbol {} has not been loaded", stringify!($name));
40 }
41 };
42 (extern "C" {
43 $(fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+
44 }) => {
45 struct Napi {
46 $(
47 $name: unsafe extern "C" fn(
48 $($param: $ptype,)*
49 )$( -> $rtype)*,
50 )*
51 }
52
53 static mut NAPI: Napi = {
54 $(
55 generate!(@stub_fn $name($($param: $ptype,)*) $( -> $rtype)?);
56 )*
57
58 Napi {
59 $(
60 $name,
61 )*
62 }
63 };
64
65 #[allow(clippy::missing_safety_doc)]
66 pub unsafe fn load(
67 host: &libloading::Library,
68 ) -> Result<(), libloading::Error> {
69 NAPI = Napi {
70 $(
71 $name: match unsafe {
72 $crate::load_symbol(
75 host,
76 concat!(stringify!($name), "\0").as_bytes(),
77 )
78 } {
79 Some(symbol) => {
80 unsafe {
83 std::mem::transmute::<
84 *mut std::ffi::c_void,
85 unsafe extern "C" fn($(_: $ptype,)*)$( -> $rtype)*,
86 >(symbol)
87 }
88 }
89 None => NAPI.$name,
91 },
92 )*
93 };
94
95 Ok(())
96 }
97
98 $(
99 #[inline]
100 #[allow(clippy::missing_safety_doc)]
101 pub unsafe fn $name($($param: $ptype,)*)$( -> $rtype)* {
102 (NAPI.$name)($($param,)*)
103 }
104 )*
105 };
106}
107
108#[cfg(any(
109 target_family = "wasm",
110 all(not(target_env = "msvc"), not(feature = "dyn-symbols"))
111))]
112macro_rules! generate {
113 (extern "C" {
114 $(fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+
115 }) => {
116 extern "C" {
117 $(
118 pub fn $name($($param: $ptype,)*)$( -> $rtype)*;
119 ) *
120 }
121 };
122}
123
124mod functions;
125mod types;
126
127pub use functions::*;
128pub use types::*;
129
130#[cfg(any(
131 target_env = "msvc",
132 all(not(target_family = "wasm"), feature = "dyn-symbols")
133))]
134pub unsafe fn setup() -> libloading::Library {
142 match load_all() {
143 Err(err) => panic!("{}", err),
144 Ok(l) => l,
145 }
146}