ion/spec/
function.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::ffi::CStr;
8use std::ptr;
9
10use mozjs::jsapi::{JSFunctionSpec, JSNativeWrapper, JSPropertySpec_Name};
11
12use crate::flags::PropertyFlags;
13use crate::symbol::WellKnownSymbolCode;
14
15/// Creates a [function spec](JSFunctionSpec) with the given name, native function, number of arguments and flags.
16pub 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
28/// Creates a [function spec](JSFunctionSpec) with the given symbol, native function, number of arguments and flags.
29pub 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}