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

Draft: Start implementing generic wrapper types #666

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Current state
  • Loading branch information
filmor committed Jan 12, 2025
commit 88c8f7ec96bfdfa487626c8f88f798c252fc359c
8 changes: 3 additions & 5 deletions rustler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,14 @@ pub mod types;

mod term;
mod wrapped_types;
pub use crate::wrapped_types::{
ListIterator, Map
};

pub use crate::term::Term;
pub use crate::types::{
Atom, Binary, Decoder, Encoder, ErlOption, LocalPid, MapIterator, NewBinary,
OwnedBinary, Reference,
Atom, Binary, Decoder, Encoder, ErlOption, LocalPid, NewBinary, OwnedBinary
};

pub use crate::wrapped_types::{ListIterator, Reference, MapIterator, Map, Tuple};

#[cfg(feature = "big_integer")]
pub use crate::types::BigInt;

Expand Down
3 changes: 1 addition & 2 deletions rustler/src/types/elixir_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
//! `#[module = "Elixir.TheStructModule"]`.

use super::atom::{self, Atom};
use super::map::Map;
use crate::{Env, Error, NifResult, Term};
use crate::{Env, Error, Map, NifResult, Term};

pub fn get_ex_struct_name(map: Term) -> NifResult<Atom> {
// In an Elixir struct the value in the __struct__ field is always an atom.
Expand Down
17 changes: 1 addition & 16 deletions rustler/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::wrapped_types::MapIterator;
use crate::{Env, Error, NifResult, Term};

#[macro_use]
mod wrapper;

#[macro_use]
pub mod atom;
pub use crate::types::atom::Atom;
Expand All @@ -15,28 +13,15 @@ pub mod big_int;
#[cfg(feature = "big_integer")]
pub use num_bigint::BigInt;

#[doc(hidden)]
pub mod list;
pub use crate::types::list::ListIterator;

#[doc(hidden)]
pub mod map;
pub use self::map::MapIterator;

#[doc(hidden)]
pub mod primitive;
#[doc(hidden)]
pub mod string;
pub mod tuple;

#[doc(hidden)]
pub mod local_pid;
pub use self::local_pid::LocalPid;

#[doc(hidden)]
pub mod reference;
pub use self::reference::Reference;

pub mod i128;
pub mod path;

Expand Down
4 changes: 3 additions & 1 deletion rustler/src/wrapped_types/map.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//! Utilities used to access and create Erlang maps.

use super::atom;
use crate::sys::{enif_get_map_value, enif_make_map_put, enif_make_new_map};
use crate::types::atom;
use crate::wrapper::map;
use crate::{Decoder, Encoder, Env, Error, NifResult, Term, TermType};
use std::mem::MaybeUninit;
use std::ops::RangeInclusive;

use super::wrapper;

wrapper!(
/// A wrapper around an Erlang map term.
struct Map(TermType::Map)
Expand Down
12 changes: 9 additions & 3 deletions rustler/src/wrapped_types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
mod list;
mod map;
mod tuple;
mod wrapper;
mod reference;
pub mod tuple;
pub mod wrapper;

pub use list::ListIterator;
pub use map::{Map, MapIterator};
pub use reference::Reference;
pub use tuple::Tuple;

pub(crate) use wrapper::wrapper;
pub(crate) use list::ListIterator;
pub(crate) use wrapper::Wrapper;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use crate::{Env, Term, TermType};

use crate::sys::enif_make_ref;

use super::wrapper;

wrapper!{
struct Reference(TermType::Ref)
}
Expand Down
30 changes: 17 additions & 13 deletions rustler/src/wrapped_types/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::{
sys::{enif_get_tuple, ERL_NIF_TERM},
Decoder, Encoder, Env, Error, NifResult, Term, TermType,
};
use crate::{Decoder, Encoder, Env, Error, NifResult, Term, TermType};
use crate::sys::{enif_get_tuple, enif_make_tuple_from_array, ERL_NIF_TERM};

use std::{ffi::c_int, mem::MaybeUninit, ops::Index};
use std::ffi::c_int;
use std::mem::MaybeUninit;

use super::wrapper;
wrapper!(
struct Tuple(TermType::Tuple)
);
Expand Down Expand Up @@ -33,7 +34,7 @@ impl<'a> Tuple<'a> {
pub fn get(&self, index: usize) -> Option<Term<'a>> {
self.get_elements()
.get(index)
.map(|ptr| unsafe { Term::new(self.get_env(), ptr) })
.map(|ptr| unsafe { Term::new(self.get_env(), *ptr) })
}

/// Convert an Erlang tuple to a Rust vector. (To convert to a Rust tuple, use `term.decode()`
Expand All @@ -56,8 +57,13 @@ impl<'a> Tuple<'a> {
/// Convert a vector of terms to an Erlang tuple. (To convert from a Rust tuple to an Erlang tuple,
/// use `Encoder` instead.)
pub fn make_tuple<'a>(env: Env<'a>, terms: &[Term]) -> Term<'a> {
let c_terms: Vec<NIF_TERM> = terms.iter().map(|term| term.as_c_arg()).collect();
unsafe { Term::new(env, tuple::make_tuple(env.as_c_arg(), &c_terms)) }
let c_terms: Vec<ERL_NIF_TERM> = terms.iter().map(|term| term.as_c_arg()).collect();
unsafe {
let term =
enif_make_tuple_from_array(env.as_c_arg(), c_terms.as_ptr(), c_terms.len() as u32);
Term::new(env, term)
}
// unsafe { Term::new(env, tuple::make_tuple(env.as_c_arg(), &c_terms)) }
}

/// Helper macro to emit tuple-like syntax. Wraps its arguments in parentheses, and adds a comma if
Expand All @@ -83,10 +89,8 @@ macro_rules! impl_nifencoder_nifdecoder_for_tuple {
Encoder for tuple!( $( $tyvar ),* )
{
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
let arr = [ $( Encoder::encode(&self.$index, env).as_c_arg() ),* ];
unsafe {
Term::new(env, tuple::make_tuple(env.as_c_arg(), &arr))
}
let arr = [ $( Encoder::encode(&self.$index, env) ),* ];
make_tuple(env, &arr)
}
}

Expand All @@ -95,7 +99,7 @@ macro_rules! impl_nifencoder_nifdecoder_for_tuple {
{
fn decode(term: Term<'a>) -> NifResult<tuple!( $( $tyvar ),* )>
{
match unsafe { tuple::get_tuple(term.get_env().as_c_arg(), term.as_c_arg()) } {
match unsafe { get_tuple(term) } {
Ok(elements) if elements.len() == count!( $( $index ),* ) =>
Ok(tuple!( $(
(<$tyvar as Decoder>::decode(
Expand Down
6 changes: 3 additions & 3 deletions rustler/src/wrapped_types/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ macro_rules! wrapper {
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct $name<'a>(Term<'a>);

use $crate::types::wrapper::Wrapper;
use $crate::wrapped_types::Wrapper;

impl<'a> $name<'a> {
/// Returns a representation of self in the given Env.
Expand Down Expand Up @@ -83,14 +83,14 @@ macro_rules! wrapper {
type Error = $crate::Error;

fn try_from(term: Term<'a>) -> Result<Self, Self::Error> {
use $crate::types::wrapper::Wrapper;
use $crate::wrapped_types::Wrapper;
Self::wrap(term).or(Err($crate::Error::BadArg))
}
}

impl<'a> $crate::Decoder<'a> for $name<'a> {
fn decode(term: Term<'a>) -> $crate::NifResult<Self> {
use $crate::types::wrapper::Wrapper;
use $crate::wrapped_types::Wrapper;
Self::wrap(term).or(Err($crate::Error::BadArg))
}
}
Expand Down
3 changes: 1 addition & 2 deletions rustler/src/wrapper/tuple.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::sys::enif_make_tuple_from_array;
use crate::wrapper::{c_int, NIF_ENV, NIF_ERROR, NIF_TERM};
use std::mem::MaybeUninit;
use crate::wrapper::{NIF_ENV, NIF_TERM};

pub unsafe fn make_tuple(env: NIF_ENV, terms: &[NIF_TERM]) -> NIF_TERM {
enif_make_tuple_from_array(env, terms.as_ptr(), terms.len() as u32)
Expand Down