#![allow(non_camel_case_types)]
#[macro_use(enif_snprintf)]
extern crate erlang_nif_sys;
use std::marker::PhantomData;
mod wrapper;
use wrapper::nif_interface::NIF_ENV;
#[doc(hidden)]
pub mod codegen_runtime;
#[macro_use]
extern crate lazy_static;
#[macro_use]
pub mod types;
mod term;
pub use term::{ NifTerm };
pub use types::{ NifEncoder, NifDecoder };
pub mod resource;
pub mod dynamic;
pub mod schedule;
pub mod env;
pub mod thread;
mod export;
pub type NifResult<T> = Result<T, NifError>;
type EnvId<'a> = PhantomData<*mut &'a u8>;
#[derive(Clone, Copy)]
pub struct NifEnv<'a> {
env: NIF_ENV,
id: EnvId<'a>
}
impl<'a, 'b> PartialEq<NifEnv<'b>> for NifEnv<'a> {
fn eq(&self, other: &NifEnv<'b>) -> bool {
self.env == other.env
}
}
impl<'a> NifEnv<'a> {
unsafe fn new<T>(_lifetime_marker: &'a T, env: NIF_ENV) -> NifEnv<'a> {
NifEnv {
env: env,
id: PhantomData
}
}
pub fn as_c_arg(&self) -> NIF_ENV {
self.env
}
pub fn error_tuple<T>(self, reason: T) -> NifTerm<'a>
where T: NifEncoder
{
let error = types::atom::error().to_term(self);
(error, reason).encode(self)
}
}
pub enum NifError {
BadArg,
Atom(&'static str),
RaiseAtom(&'static str),
RaiseTerm(Box<NifEncoder>),
}
impl NifError {
unsafe fn encode<'a>(self, env: NifEnv<'a>) -> NifTerm<'a> {
match self {
NifError::BadArg => {
let exception = wrapper::exception::raise_badarg(env.as_c_arg());
NifTerm::new(env, exception)
},
NifError::Atom(atom_str) => {
types::atom::NifAtom::from_str(env, atom_str)
.ok().expect("NifError::Atom: bad atom").to_term(env)
},
NifError::RaiseAtom(atom_str) => {
let atom = types::atom::NifAtom::from_str(env, atom_str)
.ok().expect("NifError::RaiseAtom: bad argument");
let exception = wrapper::exception::raise_exception(
env.as_c_arg(),
atom.as_c_arg());
NifTerm::new(env, exception)
},
NifError::RaiseTerm(ref term_unencoded) => {
let term = term_unencoded.encode(env);
let exception = wrapper::exception::raise_exception(
env.as_c_arg(),
term.as_c_arg());
NifTerm::new(env, exception)
},
}
}
}