extern crate ruster_unsafe;
extern crate libc;
use super::{ NifEnv, NifTerm, NifError };
pub trait NifEncoder {
fn encode<'a>(self, env: &'a NifEnv) -> NifTerm<'a>;
}
pub trait NifDecoder: Sized {
fn decode<'a>(term: NifTerm, env: &'a NifEnv) -> Result<Self, NifError>;
}
macro_rules! impl_number_transcoder {
($typ:ty, $encode_fun:ident, $decode_fun:ident) => {
impl NifEncoder for $typ {
fn encode<'a>(self, env: &'a NifEnv) -> NifTerm<'a> {
#![allow(unused_unsafe)]
NifTerm::new(env, unsafe { ruster_unsafe::$encode_fun(env.env, self) })
}
}
impl NifDecoder for $typ {
fn decode<'a>(term: NifTerm, env: &'a NifEnv) -> Result<$typ, NifError> {
#![allow(unused_unsafe)]
let mut res: $typ = Default::default();
if unsafe { ruster_unsafe::$decode_fun(env.env, term.term, (&mut res) as *mut $typ) } == 0 {
return Err(NifError::BadArg);
}
Ok(res)
}
}
}
}
impl_number_transcoder!(libc::c_int, enif_make_int, enif_get_int);
impl_number_transcoder!(libc::c_uint, enif_make_uint, enif_get_uint);
impl_number_transcoder!(u64, enif_make_uint64, enif_get_uint64);
impl_number_transcoder!(i64, enif_make_int64, enif_get_int64);
impl_number_transcoder!(libc::c_double, enif_make_double, enif_get_double);
use super::atom::{ get_atom };
impl NifEncoder for bool {
fn encode<'a>(self, env: &'a NifEnv) -> NifTerm<'a> {
if self {
get_atom("true").unwrap().to_term(env)
} else {
get_atom("false").unwrap().to_term(env)
}
}
}
impl NifDecoder for bool {
fn decode<'a>(term: NifTerm, env: &'a NifEnv) -> Result<bool, NifError> {
Ok(super::atom::is_term_truthy(term, env))
}
}