use crate::sys::ErlNifCharEncoding::ERL_NIF_LATIN1;
use crate::sys::{
enif_get_atom, enif_get_atom_length, enif_make_atom_len, enif_make_existing_atom_len,
};
use crate::wrapper::{c_char, c_uint, NIF_ENV, NIF_TERM};
use crate::Error;
pub unsafe fn make_atom(env: NIF_ENV, name: &[u8]) -> NIF_TERM {
enif_make_atom_len(env, name.as_ptr() as *const c_char, name.len())
}
pub unsafe fn make_existing_atom(env: NIF_ENV, name: &[u8]) -> Option<NIF_TERM> {
let mut atom_out: NIF_TERM = 0;
let success = enif_make_existing_atom_len(
env,
name.as_ptr() as *const c_char,
name.len(),
&mut atom_out as *mut NIF_TERM,
ERL_NIF_LATIN1,
);
if success == 0 {
return None;
}
Some(atom_out)
}
pub unsafe fn get_atom(env: NIF_ENV, term: NIF_TERM) -> Result<String, Error> {
let mut len = 0;
let success = enif_get_atom_length(env, term, &mut len, ERL_NIF_LATIN1);
if success == 0 {
return Err(Error::BadArg);
}
let mut bytes: Vec<u8> = Vec::with_capacity(len as usize + 1);
let nbytes = enif_get_atom(env, term, bytes.as_mut_ptr(), len + 1, ERL_NIF_LATIN1);
assert!(nbytes as c_uint == len + 1);
bytes.set_len(len as usize);
let nonascii_count = bytes.iter().filter(|&&b| b >= 128).count();
if nonascii_count == 0 {
Ok(String::from_utf8_unchecked(bytes))
} else {
let mut out = String::with_capacity(bytes.len() + nonascii_count);
for b in bytes {
out.push(b as char);
}
Ok(out)
}
}