use std::ffi::{c_int, c_void, CStr};
use crate::types::{
AnyTerm, BinaryBuf, CallEnv, CallingEnv, Env, InitEnv, LocalPort, RawTerm, Raised,
Term, Tuple,
};
pub fn serialize<'id>(env: impl Env<'id>, term: impl Term<'id>) -> Option<BinaryBuf> {
let mut bin: enif_ffi::Binary = unsafe { std::mem::zeroed() };
if unsafe { enif_ffi::term_to_binary(env.raw_env(), term.raw_term(), &mut bin) } != 0 {
Some(BinaryBuf::from_filled(bin))
} else {
None
}
}
pub fn deserialize<'id>(env: impl Env<'id>, data: &[u8], safe: bool) -> Option<AnyTerm<'id>> {
let opts = if safe { enif_ffi::BIN2TERM_SAFE } else { 0 };
let mut term: RawTerm = 0;
let consumed =
unsafe { enif_ffi::binary_to_term(env.raw_env(), data.as_ptr(), data.len(), &mut term, opts) };
(consumed != 0).then(|| AnyTerm::wrap(term, env))
}
pub fn port_command<'id>(env: impl CallingEnv<'id>, port: &LocalPort, msg: impl Term<'id>) -> bool {
unsafe {
enif_ffi::port_command(env.raw_env(), &port.port, std::ptr::null_mut(), msg.raw_term()) != 0
}
}
impl<'id> CallEnv<'id> {
pub fn cpu_time(self) -> Result<Tuple<'id>, Raised<'id>> {
let raw = unsafe { enif_ffi::cpu_time(self.raw_env()) };
let term = self.check_raised(AnyTerm::wrap(raw, self))?;
Ok(Tuple::from_raw(term.raw_term()))
}
pub unsafe fn schedule_nif(
self,
fun_name: &CStr,
flags: i32,
fp: unsafe extern "C" fn(*mut enif_ffi::Env, c_int, *const enif_ffi::Term) -> enif_ffi::Term,
argc: i32,
argv: *const enif_ffi::Term,
) -> Result<AnyTerm<'id>, Raised<'id>> {
let raw =
unsafe { enif_ffi::schedule_nif(self.raw_env(), fun_name.as_ptr(), flags, fp, argc, argv) };
self.check_raised(AnyTerm::wrap(raw, self))
}
}
impl<'id> InitEnv<'id> {
pub fn set_option_delay_halt(self) -> bool {
unsafe { enif_ffi::set_option_delay_halt(self.raw_env()) == 0 }
}
pub unsafe fn set_option_on_halt(self, callback: unsafe extern "C" fn(*mut c_void)) -> bool {
unsafe { enif_ffi::set_option_on_halt(self.raw_env(), callback) == 0 }
}
pub unsafe fn set_option_on_unload_thread(
self,
callback: unsafe extern "C" fn(*mut c_void),
) -> bool {
unsafe { enif_ffi::set_option_on_unload_thread(self.raw_env(), callback) == 0 }
}
}