use crate::{ sys::{ enif_alloc_binary, enif_inspect_binary, enif_make_binary, enif_release_binary, ErlNifBinary, }, Env, Error, Result, Term, }; use std::mem::MaybeUninit; pub struct Binary(ErlNifBinary); impl Drop for Binary { fn drop(&mut self) { unsafe { enif_release_binary(&mut self.0) } } } impl Binary { pub fn new(len: usize) -> Result { let binary = unsafe { let mut binary = MaybeUninit::uninit(); let success = enif_alloc_binary(len, binary.as_mut_ptr()); if success == 0 { return Err(Error::message("failed to allocate binary")); } binary.assume_init() }; Ok(Binary(binary)) } pub fn get(&self) -> &[u8] { unsafe { std::slice::from_raw_parts(self.0.data, self.0.size) } } pub fn get_mut(&mut self) -> &mut [u8] { unsafe { std::slice::from_raw_parts_mut(self.0.data, self.0.size) } } pub fn from_bytes(bytes: &[u8]) -> Result { let mut binary = Binary::new(bytes.len())?; binary.get_mut().copy_from_slice(bytes); Ok(binary) } } pub struct BinaryTerm<'a> { term: Term<'a>, binary: Binary, } impl<'a> BinaryTerm<'a> { pub(crate) fn from_term(term: Term<'a>) -> Result> { let binary = unsafe { let mut binary = MaybeUninit::uninit(); let success = enif_inspect_binary(term.env().raw(), term.raw(), binary.as_mut_ptr()); if success == 0 { return Err(Error::message("could not inspect binary")); } binary.assume_init() }; let binary = Binary(binary); Ok(BinaryTerm { term, binary }) } pub fn term(&self) -> Term<'a> { self.term } pub fn env(&self) -> Env<'a> { self.term.env() } pub fn new(env: Env<'a>, binary: Binary) -> Result> { let mut binary = std::mem::ManuallyDrop::new(binary); let term = unsafe { enif_make_binary(env.raw(), &mut binary.0) }; let term = Term::from_raw(env, term); let term = BinaryTerm::from_term(term)?; Ok(term) } pub fn from_bytes(env: Env<'a>, bytes: &[u8]) -> Result> { let binary = Binary::from_bytes(bytes)?; let term = BinaryTerm::new(env, binary)?; Ok(term) } pub fn from_str(env: Env<'a>, string: &str) -> Result> { let binary = Binary::from_bytes(string.as_bytes())?; let term = BinaryTerm::new(env, binary)?; Ok(term) } pub fn binary(&self) -> &Binary { &self.binary } pub fn get(&self) -> Result<&[u8]> { Ok(self.binary.get()) } pub fn get_mut(&mut self) -> Result<&mut [u8]> { Ok(self.binary.get_mut()) } }