use std::panic::catch_unwind;
use types::atom::Atom;
use wrapper::exception;
use NifResult;
use {Env, Term};
pub use wrapper::nif_interface::{c_int, c_void, get_nif_resource_type_init_size, DEF_NIF_ENTRY,
DEF_NIF_FUNC, MUTABLE_NIF_RESOURCE_HANDLE, NIF_ENV,
NIF_MAJOR_VERSION, NIF_MINOR_VERSION, NIF_TERM};
#[cfg(windows)]
pub use erlang_nif_sys::{TWinDynNifCallbacks, WIN_DYN_NIF_CALLBACKS};
pub unsafe fn handle_nif_call(
function: for<'a> fn(Env<'a>, &[Term<'a>]) -> NifResult<Term<'a>>,
_arity: usize,
r_env: NIF_ENV,
argc: c_int,
argv: *const NIF_TERM,
) -> NIF_TERM {
let env_lifetime = ();
let env = Env::new(&env_lifetime, r_env);
let terms = ::std::slice::from_raw_parts(argv, argc as usize)
.iter()
.map(|x| Term::new(env, *x))
.collect::<Vec<Term>>();
let result: ::std::thread::Result<NIF_TERM> = catch_unwind(|| match function(env, &terms) {
Ok(ret) => ret.as_c_arg(),
Err(err) => err.encode(env).as_c_arg(),
});
match result {
Ok(res) => res,
Err(_err) => exception::raise_exception(
env.as_c_arg(),
Atom::from_bytes(env, b"nif_panic").ok().unwrap().as_c_arg(),
),
}
}
pub unsafe fn handle_nif_init_call(
function: Option<for<'a> fn(Env<'a>, Term<'a>) -> bool>,
r_env: NIF_ENV,
load_info: NIF_TERM,
) -> c_int {
let env_lifetime = ();
let env = Env::new(&env_lifetime, r_env);
let term = Term::new(env, load_info);
if let Some(inner) = function {
if inner(env, term) {
0
} else {
1
}
} else {
0
}
}