Skip to content
This repository has been archived by the owner on Dec 29, 2023. It is now read-only.

WIP: Add support for Erlang 22 #38

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
@@ -1,6 +1,6 @@
language: erlang
otp_release:
- 21.0
- 22.0

sudo: required

Expand Down
32 changes: 25 additions & 7 deletions gen_api.erl
Expand Up @@ -33,6 +33,9 @@ version_opts("2.13") -> [{major,2}, {minor,13}, exception, getenv, time, % erl
version_opts("2.14") -> [{major,2}, {minor,14}, exception, getenv, time, % erlang 21.0
dirty_scheduler_opt, nif_2_11, nif_2_12, nif_2_13,
nif_2_14];
version_opts("2.15") -> [{major,2}, {minor,15}, exception, getenv, time, % erlang 22.0
dirty_scheduler_opt, nif_2_11, nif_2_12, nif_2_13,
nif_2_14, nif_2_15];
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).
Expand Down Expand Up @@ -228,7 +231,6 @@ api_list(Opts) -> [
{"ERL_NIF_TERM", "enif_schedule_nif", "env: *mut ErlNifEnv, fun_name: *const c_uchar, flags:c_int, fp: unsafe extern \"C\" fn(env: *mut ErlNifEnv, argc:c_int, argv:*const ERL_NIF_TERM) -> 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"},
Expand All @@ -237,16 +239,13 @@ api_list(Opts) -> [
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"},
Expand All @@ -256,13 +255,11 @@ api_list(Opts) -> [
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"},
Expand Down Expand Up @@ -321,6 +318,7 @@ api_list(Opts) -> [
];
false -> []
end ++

case proplists:get_bool(nif_2_14, Opts) of
true -> [
%% Skip iovec and synchronization APIs for now (perhaps forever).
Expand All @@ -347,6 +345,26 @@ api_list(Opts) -> [
{"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 ++

case proplists:get_bool(nif_2_15, Opts) of
true -> [
%% ERL_NIF_API_FUNC_DECL(int,enif_select_x,(ErlNifEnv* env, ErlNifEvent e, enum ErlNifSelectFlags flags, void* obj, const ErlNifPid* pid, ERL_NIF_TERM msg, ErlNifEnv* msg_env));
{"c_int", "enif_select_x", "env: *mut ErlNifEnv, e: ErlNifEvent, flags: ErlNifSelectFlags, obj: *const c_void, pid: *const ErlNifPid, msg: ERL_NIF_TERM, msg_env: *mut ErlNifEnv"},

%% ERL_NIF_API_FUNC_DECL(ERL_NIF_TERM,enif_make_monitor_term,(ErlNifEnv* env, const ErlNifMonitor*));
{"ERL_NIF_TERM", "enif_make_monitor_term", "env: *mut ErlNifEnv, monitor: *const ErlNifMonitor"},

%% ERL_NIF_API_FUNC_DECL(void,enif_set_pid_undefined,(ErlNifPid* pid));
{"c_void", "enif_set_pid_undefined", "pid: *mut ErlNifPid"},

%% ERL_NIF_API_FUNC_DECL(int,enif_is_pid_undefined,(const ErlNifPid* pid));
{"c_int", "enif_is_pid_undefined", "pid: *const ErlNifPid"},

%% ERL_NIF_API_FUNC_DECL(ErlNifTermType,enif_term_type,(ErlNifEnv* env, ERL_NIF_TERM term));
{"ErlNifTermType", "enif_term_type", "env: *mut ErlNifEnv, term: ERL_NIF_TERM"}
];
false -> []
end.


Expand Down Expand Up @@ -392,7 +410,7 @@ api_bindings_rust("win32", Entries) ->
% The line below would be the "faithful" reproduction of the NIF Win API, but Rust
% is currently not allowing statics to be uninitialized (1.3 beta). Revisit this when
% RFC911 is implemented (or some other mechanism)
%"static mut WinDynNifCallbacks:TWinDynNifCallbacks = unsafe{std::mem::uninitialized()};\n\n",
%"static mut WinDynNifCallbacks:TWinDynNifCallbacks = unsafe{std::mem::MaybeUninit::uninit().assume_init()};\n\n",

% The work-around is to use Option. The problem here is that we have to do an unwrap() for
% each API call which is extra work.
Expand Down
26 changes: 24 additions & 2 deletions src/erlang_nif_sys_api.rs
Expand Up @@ -139,6 +139,30 @@ pub enum ErlNifResourceFlags {
ERL_NIF_RT_TAKEOVER = 2,
}


/// See [ErlNifResourceFlags](http://www.erlang.org/doc/man/erl_nif.html#ErlNifTermType) in the Erlang docs.
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub enum ErlNifTermType {
ERL_NIF_TERM_TYPE_ATOM = 1,
ERL_NIF_TERM_TYPE_BITSTRING = 2,
ERL_NIF_TERM_TYPE_FLOAT = 3,
ERL_NIF_TERM_TYPE_FUN = 4,
ERL_NIF_TERM_TYPE_INTEGER = 5,
ERL_NIF_TERM_TYPE_LIST = 6,
ERL_NIF_TERM_TYPE_MAP = 7,
ERL_NIF_TERM_TYPE_PID = 8,
ERL_NIF_TERM_TYPE_PORT = 9,
ERL_NIF_TERM_TYPE_REFERENCE = 10,
ERL_NIF_TERM_TYPE_TUPLE = 11,

/// This is a dummy value intended to coax the compiler into warning about
/// unhandled values in a switch even if all the above values have been
/// handled. We can add new entries at any time so the user must always
/// have a default case.
ERL_NIF_TERM_TYPE__MISSING_DEFAULT_CASE__READ_THE_MANUAL = -1
}

/// See [ErlNifCharEncoding](http://www.erlang.org/doc/man/erl_nif.html#ErlNifCharEncoding) in the Erlang docs.
#[derive(Debug, Copy, Clone)]
#[repr(C)]
Expand Down Expand Up @@ -275,5 +299,3 @@ include!(concat!(env!("OUT_DIR"), "/nif_api.snippet"));
// pub fn enif_is_atom(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
// pub fn enif_is_binary(arg1: *mut ErlNifEnv, term: ERL_NIF_TERM) -> c_int;
// ...


5 changes: 2 additions & 3 deletions src/initmacro.rs
@@ -1,4 +1,3 @@

/// Implement exported module init function needed by the Erlang runtime.
///
/// See [the module level documentation](index.html) for usage of `nif_init!`.
Expand Down Expand Up @@ -69,8 +68,8 @@ macro_rules! platform_nif_init {
/// fn native_add(env: *mut ErlNifEnv,
/// args: &[ERL_NIF_TERM]) -> ERL_NIF_TERM {
/// unsafe {
/// let mut a: c_int = mem::uninitialized();
/// let mut b: c_int = mem::uninitialized();
/// let mut a: c_int = mem::MaybeUninit::uninit().assume_init();
/// let mut b: c_int = mem::MaybeUninit::uninit().assume_init();
/// if args.len() == 2 &&
/// 0 != enif_get_int(env, args[0], &mut a) &&
/// 0 != enif_get_int(env, args[1], &mut b) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Expand Up @@ -110,8 +110,8 @@ fn native_add(env: *mut ErlNifEnv,
argc: c_int,
args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {
unsafe {
let mut a: c_int = mem::uninitialized();
let mut b: c_int = mem::uninitialized();
let mut a: c_int = mem::MaybeUninit();
let mut b: c_int = mem::MaybeUninit();
if argc == 2 &&
0 != enif_get_int(env, *args, &mut a) &&
0 != enif_get_int(env, *args.offset(1), &mut b) {
Expand Down
26 changes: 21 additions & 5 deletions tests/testapp/crates/mynifmod/src/lib.rs
@@ -1,5 +1,4 @@

#[macro_use]
extern crate erlang_nif_sys;
use erlang_nif_sys::*;

Expand All @@ -13,6 +12,8 @@ static mut DTOR_COUNTER: Option<AtomicIsize> = None;
nif_init!("mynifmod", [
("times2", 1, slice_args!(times2)),
("test_enif_make_pid", 0, test_enif_make_pid),
("test_enif_set_pid_undefined", 0, test_enif_set_pid_undefined),
("test_enif_is_pid_undefined", 0, test_enif_is_pid_undefined),
("rustmap", 0, rustmap),
("rustmap_dtor_count", 0, rustmap_dtor_count),
("to_str", 1, slice_args!(to_str)),
Expand All @@ -22,7 +23,7 @@ nif_init!("mynifmod", [
{load: mynifmod_load});

unsafe fn mynifmod_load(env: *mut ErlNifEnv, _priv_data: *mut *mut c_void, _load_info: ERL_NIF_TERM) -> c_int {
let mut tried: ErlNifResourceFlags = mem::uninitialized();
let mut tried: ErlNifResourceFlags = mem::MaybeUninit::uninit().assume_init();
DTOR_COUNTER = Some(AtomicIsize::new(0));
RUSTMAP_TYPE = enif_open_resource_type(
env,
Expand All @@ -36,7 +37,7 @@ unsafe fn mynifmod_load(env: *mut ErlNifEnv, _priv_data: *mut *mut c_void, _load

fn times2(env: *mut ErlNifEnv, args: &[ERL_NIF_TERM]) -> ERL_NIF_TERM {
unsafe {
let mut result: i32 = mem::uninitialized();
let mut result: i32 = mem::MaybeUninit::uninit().assume_init();
if 1==args.len() && 0!=enif_get_int(env, args[0], &mut result) {
enif_make_int(env, 2*result)
}
Expand All @@ -47,11 +48,26 @@ fn times2(env: *mut ErlNifEnv, args: &[ERL_NIF_TERM]) -> ERL_NIF_TERM {
}

fn test_enif_make_pid(env: *mut ErlNifEnv, _: c_int, _: *const ERL_NIF_TERM) -> ERL_NIF_TERM {
let mut pid: ErlNifPid = unsafe { mem::uninitialized() };
let mut pid: ErlNifPid = unsafe { mem::MaybeUninit::uninit().assume_init() };
unsafe { enif_self(env, &mut pid) };
unsafe { enif_make_pid(env, &pid) }
}

fn test_enif_set_pid_undefined() {
unsafe {
let mut pid: ErlNifPid = unsafe { mem::MaybeUninit::uninit().assume_init() };
let pid_undefined = Some(enif_set_pid_undefined(&mut pid));
assert!(pid_undefined.is_none());
}
}

fn test_enif_is_pid_undefined() {
unsafe {
let mut pid: ErlNifPid = unsafe { mem::MaybeUninit::uninit().assume_init() };
assert_eq!(1, enif_is_pid_undefined(&pid));
}
}

use std::collections::HashMap;
type RustMap = HashMap<String, String>;

Expand Down Expand Up @@ -114,7 +130,7 @@ unsafe fn make_map(env: *mut ErlNifEnv, args: &[ERL_NIF_TERM]) -> ERL_NIF_TERM {
let values: Vec<_> = (1..=3)
.map(|x| enif_make_int(env, x))
.collect();
let mut map = mem::uninitialized();
let mut map = mem::MaybeUninit::uninit().assume_init();
if 0!=enif_make_map_from_arrays(env, keys.as_ptr(), values.as_ptr(), keys.len(), &mut map) {
map
} else {
Expand Down
4 changes: 4 additions & 0 deletions tests/testapp/mynifmod.erl
Expand Up @@ -29,6 +29,8 @@ exercise_dtor(N) ->
simple_test_() -> [
?_assertEqual(6, times2(3)),
?_assertEqual(self(), test_enif_make_pid()),
? assertEqual(true, test_enif_set_pid_undefined()),
? assertEqual(true, test_enif_id_pid_undefined()),
fun() -> rustmap() end,
?_assertEqual(11, exercise_dtor(10)),
?_assertEqual("123", to_str(123)),
Expand All @@ -44,6 +46,8 @@ simple_test_() -> [

times2(_X) -> exit(nif_library_not_loaded).
test_enif_make_pid() -> exit(nif_library_not_loaded).
test_enif_set_pid_undefined() -> exit(nif_library_not_loaded).
test_enif_id_pid_undefined() -> exit(nif_library_not_loaded).
rustmap() -> exit(nif_library_not_loaded).
rustmap_dtor_count() -> exit(nif_library_not_loaded).
to_str(_X) -> exit(nif_library_not_loaded).
Expand Down