-type api_opt() ::
exception | getenv | time | {ulongsize, integer()} | dirty_schedulers | dirty_scheduler_opt | nif_2_11 .
version_opts("2.7") -> [{major,2}, {minor,7} ]; version_opts("2.8") -> [{major,2}, {minor,8}, exception]; version_opts("2.9") -> [{major,2}, {minor,9}, exception, getenv]; version_opts("2.10") -> [{major,2}, {minor,10}, exception, getenv, time]; version_opts("2.11") -> [{major,2}, {minor,11}, exception, getenv, time, dirty_scheduler_opt, nif_2_11];
version_opts("2.12") -> [{major,2}, {minor,12}, exception, getenv, time, dirty_scheduler_opt, nif_2_11, nif_2_12];
version_opts("2.13") -> [{major,2}, {minor,13}, exception, getenv, time, dirty_scheduler_opt, nif_2_11, nif_2_12, nif_2_13];
version_opts("2.14") -> [{major,2}, {minor,14}, exception, getenv, time, dirty_scheduler_opt, nif_2_11, nif_2_12, nif_2_13,
nif_2_14];
version_opts(_) ->
io:format("Unsupported Erlang version.\n\nIs the erlang_nif-sys version up to date in the Cargo.toml?\nDoes 'cargo update' fix it?\nIf not please report at https://github.com/goertzenator/erlang_nif-sys.\n"),
halt(1).
ulong_opts("4") -> [{ulongsize, 4}];
ulong_opts("8") -> [{ulongsize, 8}].
dirty_scheduler_opts("2.7") -> dirty_scheduler_opts();
dirty_scheduler_opts("2.8") -> dirty_scheduler_opts();
dirty_scheduler_opts("2.9") -> dirty_scheduler_opts();
dirty_scheduler_opts("2.10") -> dirty_scheduler_opts();
dirty_scheduler_opts(_) -> [].
dirty_scheduler_opts() ->
case catch erlang:system_info(dirty_cpu_schedulers) of
_X when is_integer(_X) -> [dirty_schedulers, dirty_scheduler_opt];
_ -> []
end.
-spec api_list([api_opt()]) -> [term()].
api_list(Opts) -> [
{"*mut c_void", "enif_priv_data", "arg1: *mut ErlNifEnv"},
{"*mut c_void", "enif_alloc", "size: size_t"},
{"", "enif_free", "ptr: *mut c_void"},
{"c_int", "enif_is_atom", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_is_binary", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_is_ref", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_inspect_binary", "arg1: *mut ErlNifEnv, bin_term: ERL_NIF_TERM, bin: *mut ErlNifBinary"},
{"c_int", "enif_alloc_binary", "size: size_t, bin: *mut ErlNifBinary"},
{"c_int", "enif_realloc_binary", "bin: *mut ErlNifBinary, size: size_t"},
{"", "enif_release_binary", "bin: *mut ErlNifBinary"},
{"c_int", "enif_get_int", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut c_int"},
{"c_int", "enif_get_ulong", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut c_ulong"},
{"c_int", "enif_get_double", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, dp: *mut c_double"},
{"c_int", "enif_get_list_cell", "env: *mut ErlNifEnv, term: ERL_NIF_TERM, head: *mut ERL_NIF_TERM, tail: *mut ERL_NIF_TERM"},
{"c_int", "enif_get_tuple", "env: *mut ErlNifEnv, tpl: ERL_NIF_TERM, arity: *mut c_int, array: *mut *const ERL_NIF_TERM"},
{"c_int", "enif_is_identical", "lhs: ERL_NIF_TERM, rhs: ERL_NIF_TERM"},
{"c_int", "enif_compare", "lhs: ERL_NIF_TERM, rhs: ERL_NIF_TERM"},
{"ERL_NIF_TERM", "enif_make_binary", "env: *mut ErlNifEnv, bin: *mut ErlNifBinary"},
{"ERL_NIF_TERM", "enif_make_badarg", "env: *mut ErlNifEnv"},
{"ERL_NIF_TERM", "enif_make_int", "env: *mut ErlNifEnv, i: c_int"},
{"ERL_NIF_TERM", "enif_make_ulong", "env: *mut ErlNifEnv, i: c_ulong"},
{"ERL_NIF_TERM", "enif_make_double", "env: *mut ErlNifEnv, d: c_double"},
{"ERL_NIF_TERM", "enif_make_atom", "env: *mut ErlNifEnv, name: *const c_uchar"},
{"c_int", "enif_make_existing_atom", "env: *mut ErlNifEnv, name: *const c_uchar, atom: *mut ERL_NIF_TERM, arg1: ErlNifCharEncoding"},
{"ERL_NIF_TERM", "enif_make_tuple", "env: *mut ErlNifEnv, cnt: c_uint, ..."},
{"ERL_NIF_TERM", "enif_make_list", "env: *mut ErlNifEnv, cnt: c_uint, ..."},
{"ERL_NIF_TERM", "enif_make_list_cell", "env: *mut ErlNifEnv, car: ERL_NIF_TERM, cdr: ERL_NIF_TERM"},
{"ERL_NIF_TERM", "enif_make_string", "env: *mut ErlNifEnv, string: *const c_uchar, arg1: ErlNifCharEncoding"},
{"ERL_NIF_TERM", "enif_make_ref", "env: *mut ErlNifEnv"},
{"", "dummy_enif_mutex_create", ""},
{"", "dummy_enif_mutex_destroy", ""},
{"", "dummy_enif_mutex_trylock", ""},
{"", "dummy_enif_mutex_lock", ""},
{"", "dummy_enif_mutex_unlock", ""},
{"", "dummy_enif_cond_create", ""},
{"", "dummy_enif_cond_destroy", ""},
{"", "dummy_enif_cond_signal", ""},
{"", "dummy_enif_cond_broadcast", ""},
{"", "dummy_enif_cond_wait", ""},
{"", "dummy_enif_rwlock_create", ""},
{"", "dummy_enif_rwlock_destroy", ""},
{"", "dummy_enif_rwlock_tryrlock", ""},
{"", "dummy_enif_rwlock_rlock", ""},
{"", "dummy_enif_rwlock_runlock", ""},
{"", "dummy_enif_rwlock_tryrwlock", ""},
{"", "dummy_enif_rwlock_rwlock", ""},
{"", "dummy_enif_rwlock_rwunlock", ""},
{"", "dummy_enif_tsd_key_create", ""},
{"", "dummy_enif_tsd_key_destroy", ""},
{"", "dummy_enif_tsd_set", ""},
{"", "dummy_enif_tsd_get", ""},
{"", "dummy_enif_thread_opts_create", ""},
{"", "dummy_enif_thread_opts_destroy", ""},
{"", "dummy_enif_thread_create", ""},
{"", "dummy_enif_thread_self", ""},
{"", "dummy_enif_equal_tids", ""},
{"", "dummy_enif_thread_exit", ""},
{"", "dummy_enif_thread_join", ""},
{"*mut c_void", "enif_realloc", "ptr: *mut c_void, size: size_t"},
{"", "enif_system_info", "sip: *mut ErlNifSysInfo, si_size: size_t"},
{"c_int", "enif_fprintf", "filep: *mut c_void, format: *const c_uchar, ..."},
{"c_int", "enif_inspect_iolist_as_binary", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, bin: *mut ErlNifBinary"},
{"ERL_NIF_TERM", "enif_make_sub_binary", "arg1: *mut ErlNifEnv, bin_term: ERL_NIF_TERM, pos: size_t, size: size_t"},
{"c_int", "enif_get_string", "arg1: *mut ErlNifEnv, list: ERL_NIF_TERM, buf: *mut c_uchar, len: c_uint, arg2: ErlNifCharEncoding"},
{"c_int", "enif_get_atom", "arg1: *mut ErlNifEnv, atom: ERL_NIF_TERM, buf: *mut c_uchar, len: c_uint, arg2: ErlNifCharEncoding"},
{"c_int", "enif_is_fun", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_is_pid", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_is_port", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_get_uint", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut c_uint"},
{"c_int", "enif_get_long", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut c_long"},
{"ERL_NIF_TERM", "enif_make_uint", "arg1: *mut ErlNifEnv, i: c_uint"},
{"ERL_NIF_TERM", "enif_make_long", "arg1: *mut ErlNifEnv, i: c_long"},
{"ERL_NIF_TERM", "enif_make_tuple_from_array", "arg1: *mut ErlNifEnv, arr: *const ERL_NIF_TERM, cnt: c_uint"},
{"ERL_NIF_TERM", "enif_make_list_from_array", "arg1: *mut ErlNifEnv, arr: *const ERL_NIF_TERM, cnt: c_uint"},
{"c_int", "enif_is_empty_list", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"*const ErlNifResourceType", "enif_open_resource_type", "arg1: *mut ErlNifEnv, module_str: *const c_uchar, name_str: *const c_uchar, dtor: Option<unsafe extern \"C\" fn (arg1: *mut ErlNifEnv, arg2: *mut c_void)>, flags: ErlNifResourceFlags, tried: *mut ErlNifResourceFlags"},
{"*mut c_void", "enif_alloc_resource", "_type: *const ErlNifResourceType, size: size_t"},
{"", "enif_release_resource", "obj: *const c_void"},
{"ERL_NIF_TERM", "enif_make_resource", "arg1: *mut ErlNifEnv, obj: *const c_void"},
{"c_int", "enif_get_resource", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, _type: *const ErlNifResourceType, objp: *mut *const c_void"},
{"size_t", "enif_sizeof_resource", "obj: *const c_void"},
{"*mut c_uchar", "enif_make_new_binary", "arg1: *mut ErlNifEnv, size: size_t, termp: *mut ERL_NIF_TERM"},
{"c_int", "enif_is_list", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_is_tuple", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_get_atom_length", "arg1: *mut ErlNifEnv, atom: ERL_NIF_TERM, len: *mut c_uint, arg2: ErlNifCharEncoding"},
{"c_int", "enif_get_list_length", "env: *mut ErlNifEnv, term: ERL_NIF_TERM, len: *mut c_uint"},
{"ERL_NIF_TERM", "enif_make_atom_len", "env: *mut ErlNifEnv, name: *const c_uchar, len: size_t"},
{"c_int", "enif_make_existing_atom_len", "env: *mut ErlNifEnv, name: *const c_uchar, len: size_t, atom: *mut ERL_NIF_TERM, arg1: ErlNifCharEncoding"},
{"ERL_NIF_TERM", "enif_make_string_len", "env: *mut ErlNifEnv, string: *const c_uchar, len: size_t, arg1: ErlNifCharEncoding"},
{"*mut ErlNifEnv", "enif_alloc_env", ""},
{"", "enif_free_env", "env: *mut ErlNifEnv"},
{"", "enif_clear_env", "env: *mut ErlNifEnv"},
{"c_int", "enif_send", "env: *mut ErlNifEnv, to_pid: *const ErlNifPid, msg_env: *mut ErlNifEnv, msg: ERL_NIF_TERM"},
{"ERL_NIF_TERM", "enif_make_copy", "dst_env: *mut ErlNifEnv, src_term: ERL_NIF_TERM"},
{"*mut ErlNifPid", "enif_self", "caller_env: *mut ErlNifEnv, pid: *mut ErlNifPid"},
{"c_int", "enif_get_local_pid", "env: *mut ErlNifEnv, arg1: ERL_NIF_TERM, pid: *mut ErlNifPid"},
{"", "enif_keep_resource", "obj: *const c_void"},
{"ERL_NIF_TERM", "enif_make_resource_binary", "arg1: *mut ErlNifEnv, obj: *const c_void, data: *const c_void, size: size_t"}
] ++
case proplists:get_value(ulongsize, Opts) of
8 -> [];
4 ->
[
{"c_int", "enif_get_int64", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut c_longlong"},
{"c_int", "enif_get_uint64", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut c_ulonglong"},
{"ERL_NIF_TERM", "enif_make_int64", "env: *mut ErlNifEnv, i: c_longlong"},
{"ERL_NIF_TERM", "enif_make_uint64", "env: *mut ErlNifEnv, i: c_ulonglong"}
]
end ++ [
{"c_int", "enif_is_exception", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_make_reverse_list", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM, list: *mut ERL_NIF_TERM"},
{"c_int", "enif_is_number", "arg1: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"*mut c_void", "enif_dlopen", "lib: *const c_uchar, err_handler: Option<unsafe extern \"C\" fn (arg1: *mut c_void, arg2: *const c_uchar)>, err_arg: *mut c_void"},
{"*mut c_void", "enif_dlsym", "handle: *mut c_void, symbol: *const c_uchar, err_handler: Option<unsafe extern \"C\" fn (arg1: *mut c_void, arg2: *const c_uchar)>, err_arg: *mut c_void"},
{"c_int", "enif_consume_timeslice", "arg1: *mut ErlNifEnv, percent: c_int"},
{"c_int", "enif_is_map", "env: *mut ErlNifEnv, term: ERL_NIF_TERM"},
{"c_int", "enif_get_map_size", "env: *mut ErlNifEnv, term: ERL_NIF_TERM, size: *mut size_t"},
{"ERL_NIF_TERM", "enif_make_new_map", "env: *mut ErlNifEnv"},
{"c_int", "enif_make_map_put", "env: *mut ErlNifEnv, map_in: ERL_NIF_TERM, key: ERL_NIF_TERM, value: ERL_NIF_TERM, map_out: *mut ERL_NIF_TERM"},
{"c_int", "enif_get_map_value", "env: *mut ErlNifEnv, map: ERL_NIF_TERM, key: ERL_NIF_TERM, value: *mut ERL_NIF_TERM"},
{"c_int", "enif_make_map_update", "env: *mut ErlNifEnv, map_in: ERL_NIF_TERM, key: ERL_NIF_TERM, value: ERL_NIF_TERM, map_out: *mut ERL_NIF_TERM"},
{"c_int", "enif_make_map_remove", "env: *mut ErlNifEnv, map_in: ERL_NIF_TERM, key: ERL_NIF_TERM, map_out: *mut ERL_NIF_TERM"},
{"c_int", "enif_map_iterator_create", "env: *mut ErlNifEnv, map: ERL_NIF_TERM, iter: *mut ErlNifMapIterator, entry: ErlNifMapIteratorEntry"},
{"", "enif_map_iterator_destroy", "env: *mut ErlNifEnv, iter: *mut ErlNifMapIterator"},
{"c_int", "enif_map_iterator_is_head", "env: *mut ErlNifEnv, iter: *mut ErlNifMapIterator"},
{"c_int", "enif_map_iterator_is_tail", "env: *mut ErlNifEnv, iter: *mut ErlNifMapIterator"},
{"c_int", "enif_map_iterator_next", "env: *mut ErlNifEnv, iter: *mut ErlNifMapIterator"},
{"c_int", "enif_map_iterator_prev", "env: *mut ErlNifEnv, iter: *mut ErlNifMapIterator"},
{"c_int", "enif_map_iterator_get_pair", "env: *mut ErlNifEnv, iter: *mut ErlNifMapIterator, key: *mut ERL_NIF_TERM, value: *mut ERL_NIF_TERM"},
{"ERL_NIF_TERM", "enif_schedule_nif", "env: *mut ErlNifEnv, fun_name: *const c_uchar, flags:c_int, dtor: Option<unsafe extern \"C\" fn(env: *mut ErlNifEnv, argc:c_int, argv:*const ERL_NIF_TERM)>, argc:c_int, argv:*const ERL_NIF_TERM"}
] ++
case proplists:get_bool(exception, Opts) of
true -> [
{"c_int", "enif_has_pending_exception", "env: *mut ErlNifEnv, reason: *mut ERL_NIF_TERM"},
{"ERL_NIF_TERM", "enif_raise_exception", "env: *mut ErlNifEnv, reason: ERL_NIF_TERM"}
];
false -> []
end ++
case proplists:get_bool(getenv, Opts) of
true -> [
{"c_int", "enif_getenv", "key: *const c_uchar, value: *mut c_uchar, value_size: *mut size_t"}
];
false -> []
end ++
case proplists:get_bool(time, Opts) of
true -> [
{"ErlNifTime", "enif_monotonic_time", "unit: ErlNifTimeUnit"},
{"ErlNifTime", "enif_time_offset", "unit: ErlNifTimeUnit"},
{"ErlNifTime", "enif_convert_time_unit", "time: ErlNifTime, from_unit: ErlNifTimeUnit, to_unit: ErlNifTimeUnit"}
];
false -> []
end ++
case proplists:get_bool(dirty_schedulers, Opts) of
true -> [{"c_int", "enif_is_on_dirty_scheduler", "env: *mut ErlNifEnv"} ];
false -> []
end ++
case proplists:get_bool(nif_2_11, Opts) of
true -> [
{"ERL_NIF_TERM", "enif_now_time", "env: *mut ErlNifEnv"},
{"ERL_NIF_TERM", "enif_cpu_time", "env: *mut ErlNifEnv"},
{"ERL_NIF_TERM", "enif_make_unique_integer", "env: *mut ErlNifEnv, properties: ErlNifUniqueInteger"},
{"c_int", "enif_is_current_process_alive", "env: *mut ErlNifEnv"},
{"c_int", "enif_is_process_alive", "env: *mut ErlNifEnv, pid: *const ErlNifPid"},
{"c_int", "enif_is_port_alive", "env: *mut ErlNifEnv, port_id: *const ErlNifPort"},
{"c_int", "enif_get_local_port", "env: *mut ErlNifEnv, term: ERL_NIF_TERM, port_id: *mut ErlNifPort"},
{"c_int", "enif_term_to_binary", "env: *mut ErlNifEnv, term: ERL_NIF_TERM, bin: *mut ErlNifBinary"},
{"usize", "enif_binary_to_term", "env: *mut ErlNifEnv, data: *const c_uchar, sz: usize, term: *mut ERL_NIF_TERM, opts: ErlNifBinaryToTerm"},
{"c_int", "enif_port_command", "env: *mut ErlNifEnv, to_port: *const ErlNifPort, msg_env: *mut ErlNifEnv, msg: ERL_NIF_TERM"},
{"c_int", "enif_thread_type", ""},
{"c_int", "enif_snprintf", "out: *mut c_char, size: usize, format: *const c_char, ..."}
];
false -> []
end ++
case proplists:get_bool(nif_2_12, Opts) of
true -> [
{"c_int", "enif_select", "env: *mut ErlNifEnv, e: ErlNifEvent, flags: ErlNifSelectFlags, obj: *const c_void, pid: *const ErlNifPid, eref: ERL_NIF_TERM"},
{"*const ErlNifResourceType", "enif_open_resource_type_x", "env: *mut ErlNifEnv, name_str: *const c_uchar, init: *const ErlNifResourceTypeInit, flags: ErlNifResourceFlags, tried: *mut ErlNifResourceFlags"},
{"c_int", "enif_monitor_process", "env: *mut ErlNifEnv, obj: *const c_void, pid: *const ErlNifPid, monitor: *mut ErlNifMonitor"},
{"c_int", "enif_demonitor_process", "env: *mut ErlNifEnv, obj: *const c_void, monitor: *const ErlNifMonitor"},
{"c_int", "enif_compare_monitors", "monitor1: *const ErlNifMonitor, monitor2: *const ErlNifMonitor"},
{"u64", "enif_hash", "hashtype: ErlNifHash, term: ERL_NIF_TERM, salt: u64"},
{"c_int", "enif_whereis_pid", "env: *mut ErlNifEnv, name: ERL_NIF_TERM, pid: *mut ErlNifPid"},
{"c_int", "enif_whereis_port", "env: *mut ErlNifEnv, name: ERL_NIF_TERM, port: *mut ErlNifPort"}
];
false -> []
end ++
case proplists:get_bool(nif_2_13, Opts) of
true -> [
{"", "dummy_enif_ioq_create", ""},
{"", "dummy_enif_ioq_destroy", ""},
{"", "dummy_enif_ioq_enq_binary", ""},
{"", "dummy_enif_ioq_enqv", ""},
{"", "dummy_enif_ioq_size", ""},
{"", "dummy_enif_ioq_deq", ""},
{"", "dummy_enif_ioq_peek", ""},
{"", "dummy_enif_inspect_iovec", ""},
{"", "dummy_enif_free_iovec", ""}
];
false -> []
end ++
case proplists:get_bool(nif_2_14, Opts) of
true -> [
{"", "dummy_enif_ioq_peek_head", ""},
{"", "dummy_enif_mutex_name", ""},
{"", "dummy_enif_cond_name", ""},
{"", "dummy_enif_rwlock_name", ""},
{"", "dummy_enif_thread_name", ""},
{"", "dummy_enif_vfprintf", ""},
{"", "dummy_enif_vsnprintf", ""},
{"c_int", "enif_make_map_from_arrays", "env: *mut ErlNifEnv, keys: *const ERL_NIF_TERM, values: *const ERL_NIF_TERM, cnt: usize, map_out: *mut ERL_NIF_TERM"}
];
false -> []
end.
main([UlongSizeT]) -> main([UlongSizeT,"."]);
main([UlongSizeT, OutputDir]) ->
Version = (catch erlang:system_info(nif_version)),
Opts = version_opts(Version) ++ ulong_opts(UlongSizeT) ++ dirty_scheduler_opts(Version),
Entries = api_list(Opts),
Rust = [
nif_entry_options_rust(Opts),
nif_version_rust(proplists:get_value(major, Opts), proplists:get_value(minor, Opts)),
api_bindings_rust(erlang:system_info(system_architecture), Entries),
int64_mappers_rust(proplists:get_value(ulongsize, Opts))
],
Filename = filename:join(OutputDir, "nif_api.snippet"),
file:write_file(Filename, Rust),
ok.
nif_entry_options_rust(Opts) ->
DirtySchedulerOpt = proplists:get_bool(dirty_scheduler_opt, Opts),
case DirtySchedulerOpt of
true -> "pub const ERL_NIF_ENTRY_OPTIONS: c_uint = ERL_NIF_DIRTY_NIF_OPTION;\n";
false-> "pub const ERL_NIF_ENTRY_OPTIONS: c_uint = 0;\n"
end.
nif_version_rust(Major, Minor) ->
[io_lib:format("pub const NIF_MAJOR_VERSION: c_int = ~p;\n", [Major]),
io_lib:format("pub const NIF_MINOR_VERSION: c_int = ~p;\n\n", [Minor])].
api_bindings_rust("win32", Entries) ->
[ "#[allow(dead_code)]\n",
"#[derive(Copy, Clone)]\n",
"pub struct TWinDynNifCallbacks {\n",
[io_lib:format(" ~s: ~s,\n",[Name,fn_type(Params, Return)]) || {Return,Name,Params} <- Entries],
"}\n\n",
"pub static mut WIN_DYN_NIF_CALLBACKS:Option<TWinDynNifCallbacks> = None;\n\n",
[ [ io_lib:format("/// See [~s](http://www.erlang.org/doc/man/erl_nif.html#~s) in the Erlang docs.\n", [Name, Name]),
case is_variadic(Params) of
true ->
io_lib:format("#[macro_export]\n"
"macro_rules! ~s {\n"
" ( $( $arg:expr ),* ) => { $crate::get_~s()($($arg),*) };\n"
" ( $( $arg:expr ),+, ) => { ~s!($($arg),*) };\n"
"}\n\n"
"#[inline]\n"
"#[doc(hidden)]\n"
"pub unsafe fn get_~s() -> ~s {\n"
" WIN_DYN_NIF_CALLBACKS.unchecked_unwrap().~s\n"
"}\n\n",
[Name,Name,Name,Name,fn_type(Params, Return),Name]);
_ ->
io_lib:format("#[inline]\n"
"pub unsafe fn ~s(~s)~s {\n"
" (WIN_DYN_NIF_CALLBACKS.unchecked_unwrap().~s)(~s)\n"
"}\n\n",
[Name,Params,ret_type(Return),Name,strip_types_from_params(Params)])
end] || {Return,Name,Params} <- Entries, not is_dummy(Name)
]
];
api_bindings_rust(_Arch, Entries) ->
[
"extern \"C\" {\n",
[ io_lib:format("/// See [~s](http://www.erlang.org/doc/man/erl_nif.html#~s) in the Erlang docs.\n"
"pub fn ~s(~s)~s;\n",
[Name,Name,Name,Params,ret_type(Return)])
|| {Return,Name,Params} <- Entries, not is_dummy(Name), not is_variadic(Params)],
"}\n\n",
[ io_lib:format("extern \"C\" {\n"
" #[doc(hidden)]\n"
" #[link_name = \"~s\"]\n"
" pub fn _~s(~s)~s;\n"
"}\n\n"
"/// See [~s](http://www.erlang.org/doc/man/erl_nif.html#~s) in the Erlang docs.\n"
"#[macro_export]\n"
"macro_rules! ~s {\n"
" ( $( $arg:expr ),* ) => { $crate::_~s($($arg),*) };\n"
" ( $( $arg:expr ),+, ) => { ~s!($($arg),*) };\n"
"}\n\n",
[Name,Name,Params,ret_type(Return),Name,Name,Name,Name,Name])
|| {Return,Name,Params} <- Entries, not is_dummy(Name), is_variadic(Params)]
].
is_dummy([$d,$u,$m,$m,$y|_]) -> true;
is_dummy(_) -> false.
is_variadic("...") -> true;
is_variadic("") -> false;
is_variadic([_|T]) -> is_variadic(T).
fn_type(Params, "") -> io_lib:format("extern \"C\" fn (~s)", [Params]);
fn_type(Params, Return) -> io_lib:format("extern \"C\" fn (~s) -> ~s", [Params, Return]).
ret_type("") -> "";
ret_type(Return) -> " -> " ++ Return.
strip_types_from_params(Params) ->
ParamsCleaned0 = re:replace(Params, " ", ""), ParamsCleaned = re:replace(ParamsCleaned0, "\\(.*\\)", ""), ParamsL = re:split(ParamsCleaned, ","),
ArgsL = [ re:replace(Param, ":.*", "") || Param <- ParamsL ], join(ArgsL, ", ").
join(List, Joiner) -> join([], List, Joiner).
join(Acc, [H], _Joiner) -> lists:reverse([H|Acc]);
join(Acc, [H|T], Joiner) -> join([Joiner, H|Acc], T, Joiner).
int64_mappers_rust(4) ->
"use std::os::raw::{c_ulonglong, c_longlong};";
int64_mappers_rust(8) -> join([
"/// See [enif_make_int64](http://www.erlang.org/doc/man/erl_nif.html#enif_make_int64) at erlang.org",
"#[inline]",
"pub unsafe fn enif_make_int64(env: *mut ErlNifEnv, i: i64) -> ERL_NIF_TERM",
" { enif_make_long(env, i) }",
"",
"/// See [enif_make_uint64](http://www.erlang.org/doc/man/erl_nif.html#enif_make_uint64) at erlang.org",
"#[inline]",
"pub unsafe fn enif_make_uint64(env: *mut ErlNifEnv, i: u64) -> ERL_NIF_TERM",
" { enif_make_ulong(env, i) }",
"",
"/// See [enif_get_int64](http://www.erlang.org/doc/man/erl_nif.html#enif_get_int64) at erlang.org",
"#[inline]",
"pub unsafe fn enif_get_int64(env: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut i64) -> c_int",
" { enif_get_long(env, term, ip) }",
"",
"/// See [enif_get_uint64](http://www.erlang.org/doc/man/erl_nif.html#enif_get_uint64) at erlang.org",
"#[inline]",
"pub unsafe fn enif_get_uint64(env: *mut ErlNifEnv, term: ERL_NIF_TERM, ip: *mut u64) -> c_int",
" { enif_get_ulong(env, term, ip) }"],
"\n").