1use std::ffi::CStr;
8use std::ptr;
9
10use mozjs::jsapi::{JSFunctionSpec, JSNativeWrapper, JSPropertySpec_Name};
11
12use crate::flags::PropertyFlags;
13use crate::symbol::WellKnownSymbolCode;
14
15pub const fn create_function_spec(
17 name: &'static CStr, func: JSNativeWrapper, nargs: u16, flags: PropertyFlags,
18) -> JSFunctionSpec {
19 JSFunctionSpec {
20 name: JSPropertySpec_Name { string_: name.as_ptr().cast() },
21 call: func,
22 nargs,
23 flags: flags.bits(),
24 selfHostedName: ptr::null_mut(),
25 }
26}
27
28pub const fn create_function_spec_symbol(
30 symbol: WellKnownSymbolCode, func: JSNativeWrapper, nargs: u16, flags: PropertyFlags,
31) -> JSFunctionSpec {
32 JSFunctionSpec {
33 name: JSPropertySpec_Name { symbol_: symbol as u32 as usize + 1 },
34 call: func,
35 nargs,
36 flags: flags.bits(),
37 selfHostedName: ptr::null_mut(),
38 }
39}
40
41#[cfg(feature = "macros")]
42#[doc(hidden)]
43pub const fn __cstr_from_utf8_with_nul(s: &str) -> &CStr {
44 let bytes = s.as_bytes();
45 assert!(
46 bytes.is_empty() || bytes[bytes.len() - 1] == b'\0',
47 "string is not nul-terminated"
48 );
49
50 match CStr::from_bytes_with_nul(bytes) {
51 Ok(cstr) => cstr,
52 Err(_) => panic!("string contains multiple null bytes"),
53 }
54}
55
56#[cfg(feature = "macros")]
57#[macro_export(local_inner_macros)]
58macro_rules! function_spec {
59 ($function:expr, $name:expr, $nargs:expr, $flags:expr) => {
60 $crate::spec::create_function_spec(
61 $name,
62 ::mozjs::jsapi::JSNativeWrapper {
63 op: Some($function),
64 info: ::std::ptr::null_mut(),
65 },
66 $nargs,
67 $flags,
68 )
69 };
70 ($function:expr, $name:expr, $nargs:expr) => {
71 function_spec!(
72 $function,
73 $name,
74 $nargs,
75 $crate::flags::PropertyFlags::CONSTANT_ENUMERATED
76 )
77 };
78 ($function:expr, $nargs:expr) => {
79 function_spec!(
80 $function,
81 $crate::spec::__cstr_from_utf8_with_nul(std::concat!(::std::stringify!($function), "\0")),
82 $nargs
83 )
84 };
85}
86
87#[cfg(feature = "macros")]
88#[macro_export(local_inner_macros)]
89macro_rules! function_spec_symbol {
90 ($function:expr, $symbol:expr, $nargs:expr, $flags:expr) => {
91 $crate::spec::create_function_spec_symbol(
92 $symbol,
93 ::mozjs::jsapi::JSNativeWrapper {
94 op: Some($function),
95 info: ::std::ptr::null_mut(),
96 },
97 $nargs,
98 $flags,
99 )
100 };
101 ($function:expr, $symbol:expr, $nargs:expr) => {
102 create_function_spec_symbol!(
103 $function,
104 $symbol,
105 $nargs,
106 $crate::flags::PropertyFlags::CONSTANT_ENUMERATED
107 )
108 };
109}