use crate::wrapper::atom;
use crate::wrapper::NIF_TERM;
use crate::{Decoder, Encoder, Env, Error, NifResult, Term};
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct Atom {
term: NIF_TERM,
}
impl Atom {
pub fn as_c_arg(self) -> NIF_TERM {
self.term
}
pub fn to_term(self, env: Env) -> Term {
unsafe { Term::new(env, self.term) }
}
unsafe fn from_nif_term(term: NIF_TERM) -> Self {
Atom { term }
}
pub fn from_term(term: Term) -> NifResult<Self> {
if term.is_atom() {
Ok(unsafe { Atom::from_nif_term(term.as_c_arg()) })
} else {
Err(Error::BadArg)
}
}
pub fn from_bytes(env: Env, bytes: &[u8]) -> NifResult<Atom> {
if bytes.len() > 255 {
return Err(Error::BadArg);
}
unsafe { Ok(Atom::from_nif_term(atom::make_atom(env.as_c_arg(), bytes))) }
}
pub fn try_from_bytes(env: Env, bytes: &[u8]) -> NifResult<Option<Atom>> {
if bytes.len() > 255 {
return Err(Error::BadArg);
}
unsafe {
match atom::make_existing_atom(env.as_c_arg(), bytes) {
Some(term) => Ok(Some(Atom::from_nif_term(term))),
None => Ok(None),
}
}
}
pub fn from_str(env: Env, string: &str) -> NifResult<Atom> {
if string.is_ascii() {
Atom::from_bytes(env, string.as_bytes())
} else {
let mut bytes = Vec::with_capacity(string.len());
for c in string.chars() {
if (c as u32) >= 256 {
return Err(Error::BadArg);
}
bytes.push(c as u8);
}
Atom::from_bytes(env, &bytes)
}
}
}
use std::fmt;
impl fmt::Debug for Atom {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
crate::wrapper::term::fmt(self.as_c_arg(), f)
}
}
impl Encoder for Atom {
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
self.to_term(env)
}
}
impl<'a> Decoder<'a> for Atom {
fn decode(term: Term<'a>) -> NifResult<Atom> {
Atom::from_term(term)
}
}
impl<'a> PartialEq<Term<'a>> for Atom {
fn eq(&self, other: &Term<'a>) -> bool {
self.as_c_arg() == other.as_c_arg()
}
}
impl<'a> Term<'a> {
pub fn atom_to_string(&self) -> NifResult<String> {
unsafe { atom::get_atom(self.get_env().as_c_arg(), self.as_c_arg()) }
}
}
pub fn is_truthy(term: Term) -> bool {
!((term.as_c_arg() == false_().as_c_arg()) || (term.as_c_arg() == nil().as_c_arg()))
}
pub(in crate::types) fn decode_bool(term: Term) -> NifResult<bool> {
let as_c_arg = term.as_c_arg();
if as_c_arg == true_().as_c_arg() {
return Ok(true);
}
if as_c_arg == false_().as_c_arg() {
return Ok(false);
}
Err(Error::BadArg)
}
unsafe impl Sync for Atom {}
unsafe impl Send for Atom {}
#[macro_export]
macro_rules! atoms {
{
$(
$( #[$attr:meta] )*
$name:ident $( = $str:expr )?
),*$(,)?
} => {
#[allow(non_snake_case)]
struct RustlerAtoms {
$( $name : $crate::types::atom::Atom ),*
}
$crate::lazy_static::lazy_static! {
static ref RUSTLER_ATOMS: RustlerAtoms = $crate::env::OwnedEnv::new().run(|env| {
RustlerAtoms {
$( $name: $crate::atoms!(@internal_make_atom(env, $name $( = $str)? )) ),*
}
});
}
$(
$( #[$attr] )*
pub fn $name() -> $crate::types::atom::Atom {
RUSTLER_ATOMS.$name
}
)*
};
{ @internal_make_atom($env:ident, $name:ident) } => {
$crate::atoms!(@internal_make_atom($env, $name = stringify!($name)))
};
{ @internal_make_atom($env:ident, $name:ident = $str:expr) } => {
$crate::types::atom::Atom::from_str($env, $str)
.expect("rustler::atoms!: bad atom string")
};
}
#[macro_export]
#[deprecated(since = "0.22.0", note = "Please use `atoms!` instead.")]
macro_rules! rustler_atoms {
{
$(
$( #[$attr:meta] )*
atom $name:ident $( = $str:expr )?;
)*
} => {
#[allow(non_snake_case)]
struct RustlerAtoms {
$( $name : $crate::types::atom::Atom ),*
}
$crate::lazy_static::lazy_static! {
static ref RUSTLER_ATOMS: RustlerAtoms = $crate::env::OwnedEnv::new().run(|env| {
RustlerAtoms {
$( $name: $crate::rustler_atoms!(@internal_make_atom(env, $name $( = $str)? )) ),*
}
});
}
$(
$( #[$attr] )*
pub fn $name() -> $crate::types::atom::Atom {
RUSTLER_ATOMS.$name
}
)*
};
{ @internal_make_atom($env:ident, $name:ident) } => {
$crate::rustler_atoms!(@internal_make_atom($env, $name = stringify!($name)))
};
{ @internal_make_atom($env:ident, $name:ident = $str:expr) } => {
$crate::types::atom::Atom::from_str($env, $str)
.expect("rustler::atoms!: bad atom string")
};
}
atoms! {
nif_panicked,
nil,
ok,
error,
badarg,
false_ = "false",
true_ = "true",
__struct__,
first,
last,
step,
}