Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add inline tags to commonly used functions #475

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rustler/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,21 @@ impl<'a> Env<'a> {
///
/// # Unsafe
/// Don't create multiple `Env`s with the same lifetime.
#[inline]
pub unsafe fn new<T>(_lifetime_marker: &'a T, env: NIF_ENV) -> Env<'a> {
Env {
env,
id: PhantomData,
}
}

#[inline]
pub fn as_c_arg(self) -> NIF_ENV {
self.env
}

/// Convenience method for building a tuple `{error, Reason}`.
#[inline]
pub fn error_tuple<T>(self, reason: T) -> Term<'a>
where
T: Encoder,
Expand All @@ -76,6 +79,7 @@ impl<'a> Env<'a> {
/// Panics if the above rules are broken (by trying to send a message from
/// an `OwnedEnv` on a thread that's managed by the Erlang VM).
///
#[inline]
pub fn send(self, pid: &LocalPid, message: Term<'a>) {
let thread_type = unsafe { rustler_sys::enif_thread_type() };
let env = if thread_type == rustler_sys::ERL_NIF_THR_UNDEFINED {
Expand Down
6 changes: 6 additions & 0 deletions rustler/src/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@ impl<'a> Term<'a> {
/// # Unsafe
/// The caller must ensure that `env` is the environment that `inner` belongs to,
/// unless `inner` is an atom term.
#[inline]
pub unsafe fn new(env: Env<'a>, inner: NIF_TERM) -> Self {
Term { term: inner, env }
}
/// This extracts the raw term pointer. It is usually used in order to obtain a type that can
/// be passed to calls into the erlang vm.
#[inline]
pub fn as_c_arg(&self) -> NIF_TERM {
self.term
}

#[inline]
pub fn get_env(&self) -> Env<'a> {
self.env
}
Expand All @@ -45,6 +48,7 @@ impl<'a> Term<'a> {
///
/// If the term is already is in the provided env, it will be directly returned. Otherwise
/// the term will be copied over.
#[inline]
pub fn in_env<'b>(&self, env: Env<'b>) -> Term<'b> {
if self.get_env() == env {
// It's safe to create a new Term<'b> without copying because we
Expand Down Expand Up @@ -85,13 +89,15 @@ impl<'a> Term<'a> {
/// is needed.
///
/// [`decode`]: #method.decode
#[inline]
pub fn decode_as_binary(self) -> NifResult<Binary<'a>> {
if self.is_binary() {
return Binary::from_term(self);
}
Binary::from_iolist(self)
}

#[inline]
pub fn to_binary(self) -> OwnedBinary {
let raw_binary = unsafe { term_to_binary(self.env.as_c_arg(), self.as_c_arg()) }.unwrap();
unsafe { OwnedBinary::from_raw(raw_binary) }
Expand Down
14 changes: 14 additions & 0 deletions rustler/src/types/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ pub struct Binary<'a> {

impl<'a> Binary<'a> {
/// Consumes `owned` and returns an immutable `Binary`.
#[inline]
pub fn from_owned(owned: OwnedBinary, env: Env<'a>) -> Self {
// We are transferring ownership of `owned`'s data to the
// environment. Therefore, we need to prevent `owned`'s destructor being
Expand All @@ -270,6 +271,7 @@ impl<'a> Binary<'a> {
///
/// If allocation fails, an error will be returned.
#[allow(clippy::wrong_self_convention)]
#[inline]
pub fn to_owned(&self) -> Option<OwnedBinary> {
OwnedBinary::from_unowned(self)
}
Expand All @@ -279,6 +281,7 @@ impl<'a> Binary<'a> {
/// # Errors
///
/// If `term` is not a binary, an error will be returned.
#[inline]
pub fn from_term(term: Term<'a>) -> Result<Self, Error> {
let mut binary = MaybeUninit::uninit();
if unsafe {
Expand Down Expand Up @@ -316,6 +319,7 @@ impl<'a> Binary<'a> {
/// # Errors
///
/// If `term` is not an `iolist`, an error will be returned.
#[inline]
pub fn from_iolist(term: Term<'a>) -> Result<Self, Error> {
let mut binary = MaybeUninit::uninit();
if unsafe {
Expand All @@ -339,11 +343,13 @@ impl<'a> Binary<'a> {

/// Returns an Erlang term representation of `self`.
#[allow(clippy::wrong_self_convention)]
#[inline]
pub fn to_term<'b>(&self, env: Env<'b>) -> Term<'b> {
self.term.in_env(env)
}

/// Extracts a slice containing the entire binary.
#[inline]
pub fn as_slice(&self) -> &'a [u8] {
unsafe { ::std::slice::from_raw_parts(self.buf, self.size) }
}
Expand All @@ -356,6 +362,7 @@ impl<'a> Binary<'a> {
/// # Errors
///
/// If `offset + length` is out of bounds, an error will be returned.
#[inline]
pub fn make_subbinary(&self, offset: usize, length: usize) -> NifResult<Binary<'a>> {
let min_len = length.checked_add(offset);
if min_len.ok_or(Error::BadArg)? > self.size {
Expand Down Expand Up @@ -453,40 +460,47 @@ pub struct NewBinary<'a> {

impl<'a> NewBinary<'a> {
/// Allocates a new `NewBinary`
#[inline]
pub fn new(env: Env<'a>, size: usize) -> Self {
let (buf, term) = unsafe { new_binary(env, size) };
NewBinary { buf, term, size }
}
/// Extracts a slice containing the entire binary.
#[inline]
pub fn as_slice(&self) -> &[u8] {
unsafe { ::std::slice::from_raw_parts(self.buf, self.size) }
}

/// Extracts a mutable slice of the entire binary.
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { ::std::slice::from_raw_parts_mut(self.buf, self.size) }
}
}

impl<'a> From<NewBinary<'a>> for Binary<'a> {
#[inline]
fn from(new_binary: NewBinary<'a>) -> Self {
Binary::from_term(new_binary.term).unwrap()
}
}

impl<'a> From<NewBinary<'a>> for Term<'a> {
#[inline]
fn from(new_binary: NewBinary<'a>) -> Self {
new_binary.term
}
}

impl<'a> Deref for NewBinary<'a> {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
self.as_slice()
}
}
impl<'a> DerefMut for NewBinary<'a> {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
Expand Down
11 changes: 11 additions & 0 deletions rustler/src/types/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl<'a> ListIterator<'a> {
impl<'a> Iterator for ListIterator<'a> {
type Item = Term<'a>;

#[inline]
fn next(&mut self) -> Option<Term<'a>> {
let env = self.term.get_env();
let cell = unsafe { list::get_list_cell(env.as_c_arg(), self.term.as_c_arg()) };
Expand All @@ -78,6 +79,7 @@ impl<'a> Iterator for ListIterator<'a> {
}

impl<'a> Decoder<'a> for ListIterator<'a> {
#[inline]
fn decode(term: Term<'a>) -> NifResult<Self> {
match ListIterator::new(term) {
Some(iter) => Ok(iter),
Expand All @@ -97,6 +99,7 @@ impl<T> Encoder for Vec<T>
where
T: Encoder,
{
#[inline]
fn encode<'b>(&self, env: Env<'b>) -> Term<'b> {
self.as_slice().encode(env)
}
Expand All @@ -106,6 +109,7 @@ impl<'a, T> Decoder<'a> for Vec<T>
where
T: Decoder<'a>,
{
#[inline]
fn decode(term: Term<'a>) -> NifResult<Self> {
let iter: ListIterator = term.decode()?;
let res: NifResult<Self> = iter.map(|x| x.decode::<T>()).collect();
Expand All @@ -117,6 +121,7 @@ impl<T> Encoder for [T]
where
T: Encoder,
{
#[inline]
fn encode<'b>(&self, env: Env<'b>) -> Term<'b> {
let term_array: Vec<NIF_TERM> = self.iter().map(|x| x.encode(env).as_c_arg()).collect();
unsafe { Term::new(env, list::make_list(env.as_c_arg(), &term_array)) }
Expand All @@ -126,6 +131,7 @@ impl<'a, T> Encoder for &'a [T]
where
T: Encoder,
{
#[inline]
fn encode<'b>(&self, env: Env<'b>) -> Term<'b> {
let term_array: Vec<NIF_TERM> = self.iter().map(|x| x.encode(env).as_c_arg()).collect();
unsafe { Term::new(env, list::make_list(env.as_c_arg(), &term_array)) }
Expand All @@ -135,6 +141,7 @@ where
/// ## List terms
impl<'a> Term<'a> {
/// Returns a new empty list.
#[inline]
pub fn list_new_empty(env: Env<'a>) -> Term<'a> {
let list: &[u8] = &[];
list.encode(env)
Expand All @@ -144,6 +151,7 @@ impl<'a> Term<'a> {
/// See documentation for ListIterator for more information.
///
/// Returns None if the term is not a list.
#[inline]
pub fn into_list_iterator(self) -> NifResult<ListIterator<'a>> {
ListIterator::new(self).ok_or(Error::BadArg)
}
Expand All @@ -156,6 +164,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// length(self_term)
/// ```
#[inline]
pub fn list_length(self) -> NifResult<usize> {
unsafe { list::get_list_length(self.get_env().as_c_arg(), self.as_c_arg()) }
.ok_or(Error::BadArg)
Expand All @@ -171,6 +180,7 @@ impl<'a> Term<'a> {
/// [head, tail] = self_term
/// {head, tail}
/// ```
#[inline]
pub fn list_get_cell(self) -> NifResult<(Term<'a>, Term<'a>)> {
let env = self.get_env();
unsafe {
Expand All @@ -183,6 +193,7 @@ impl<'a> Term<'a> {
/// Makes a copy of the self list term and reverses it.
///
/// Returns Err(Error::BadArg) if the term is not a list.
#[inline]
pub fn list_reverse(self) -> NifResult<Term<'a>> {
let env = self.get_env();
unsafe {
Expand Down
5 changes: 5 additions & 0 deletions rustler/src/types/local_pid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ pub struct LocalPid {
}

impl LocalPid {
#[inline]
pub fn as_c_arg(&self) -> &ErlNifPid {
&self.c
}

#[inline]
pub fn from_c_arg(erl_nif_pid: ErlNifPid) -> Self {
LocalPid { c: erl_nif_pid }
}
}

impl<'a> Decoder<'a> for LocalPid {
#[inline]
fn decode(term: Term<'a>) -> NifResult<LocalPid> {
unsafe { pid::get_local_pid(term.get_env().as_c_arg(), term.as_c_arg()) }
.map(|pid| LocalPid { c: pid })
Expand All @@ -26,6 +29,7 @@ impl<'a> Decoder<'a> for LocalPid {
}

impl Encoder for LocalPid {
#[inline]
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
unsafe { Term::new(env, pid::make_pid(env.as_c_arg(), self.c)) }
}
Expand All @@ -39,6 +43,7 @@ impl<'a> Env<'a> {
/// Panics if this environment is process-independent. (The only way to get such an
/// environment is to use `OwnedEnv`. The `Env` that Rustler passes to NIFs when they're
/// called is always associated with the calling Erlang process.)
#[inline]
pub fn pid(self) -> LocalPid {
let mut pid = MaybeUninit::uninit();
if unsafe { rustler_sys::enif_self(self.as_c_arg(), pid.as_mut_ptr()) }.is_null() {
Expand Down
9 changes: 9 additions & 0 deletions rustler/src/types/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::wrapper::map;
use crate::{Decoder, Encoder, Env, Error, NifResult, Term};
use std::ops::RangeInclusive;

#[inline]
pub fn map_new(env: Env) -> Term {
unsafe { Term::new(env, map::map_new(env.as_c_arg())) }
}
Expand All @@ -17,6 +18,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// %{}
/// ```
#[inline]
pub fn map_new(env: Env<'a>) -> Term<'a> {
map_new(env)
}
Expand All @@ -29,6 +31,7 @@ impl<'a> Term<'a> {
/// values = [1, 2]
/// List.zip(keys, values) |> Map.new()
/// ```
#[inline]
pub fn map_from_arrays(
env: Env<'a>,
keys: &[impl Encoder],
Expand Down Expand Up @@ -57,6 +60,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// Map.new([{"foo", 1}, {"bar", 2}])
/// ```
#[inline]
pub fn map_from_pairs(
env: Env<'a>,
pairs: &[(impl Encoder, impl Encoder)],
Expand All @@ -81,6 +85,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// Map.get(self_term, key)
/// ```
#[inline]
pub fn map_get(self, key: impl Encoder) -> NifResult<Term<'a>> {
let env = self.get_env();
match unsafe {
Expand All @@ -99,6 +104,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// map_size(self_term)
/// ```
#[inline]
pub fn map_size(self) -> NifResult<usize> {
let env = self.get_env();
unsafe { map::get_map_size(env.as_c_arg(), self.as_c_arg()).ok_or(Error::BadArg) }
Expand All @@ -113,6 +119,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// Map.put(self_term, key, value)
/// ```
#[inline]
pub fn map_put(self, key: impl Encoder, value: impl Encoder) -> NifResult<Term<'a>> {
let env = self.get_env();

Expand All @@ -138,6 +145,7 @@ impl<'a> Term<'a> {
/// ```elixir
/// Map.delete(self_term, key)
/// ```
#[inline]
pub fn map_remove(self, key: impl Encoder) -> NifResult<Term<'a>> {
let env = self.get_env();

Expand All @@ -153,6 +161,7 @@ impl<'a> Term<'a> {
///
/// Returns Err(Error::BadArg) if the term is not a map of if key
/// doesn't exist.
#[inline]
pub fn map_update(self, key: impl Encoder, new_value: impl Encoder) -> NifResult<Term<'a>> {
let env = self.get_env();

Expand Down
2 changes: 2 additions & 0 deletions rustler/src/types/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{Decoder, Encoder, Env, Error, NifResult, Term};
macro_rules! impl_number_transcoder {
($dec_type:ty, $nif_type:ty, $encode_fun:ident, $decode_fun:ident) => {
impl Encoder for $dec_type {
#[inline]
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
#[allow(clippy::cast_lossless)]
unsafe {
Expand All @@ -15,6 +16,7 @@ macro_rules! impl_number_transcoder {
}
}
impl<'a> Decoder<'a> for $dec_type {
#[inline]
fn decode(term: Term) -> NifResult<$dec_type> {
#![allow(unused_unsafe)]
let mut res: $nif_type = Default::default();
Expand Down
Loading