From 05a50803321d2418b15382b06f23f1d466857b9f Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Thu, 24 Aug 2023 10:13:07 +0200 Subject: [PATCH] Implement get_type using enif_term_type (#538) --- rustler/src/dynamic.rs | 43 ++++++++++++++++++++++-------- rustler/src/term.rs | 5 ++++ rustler/src/types/list.rs | 2 +- rustler/src/wrapper/check.rs | 1 - rustler_sys/src/rustler_sys_api.rs | 1 + 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/rustler/src/dynamic.rs b/rustler/src/dynamic.rs index 2ffa2f7b..ad73f888 100644 --- a/rustler/src/dynamic.rs +++ b/rustler/src/dynamic.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "nif_version_2_15")] +use rustler_sys::ErlNifTermType; + use crate::wrapper::check; use crate::Term; @@ -5,12 +8,11 @@ use crate::Term; pub enum TermType { Atom, Binary, - EmptyList, - Exception, Fun, List, Map, - Number, + Integer, + Float, Pid, Port, Ref, @@ -18,23 +20,43 @@ pub enum TermType { Unknown, } +#[cfg(feature = "nif_version_2_15")] +impl From for TermType { + fn from(term_type: ErlNifTermType) -> Self { + use ErlNifTermType::*; + use TermType::*; + match term_type { + ERL_NIF_TERM_TYPE_ATOM => Atom, + ERL_NIF_TERM_TYPE_BITSTRING => Binary, + ERL_NIF_TERM_TYPE_FLOAT => Float, + ERL_NIF_TERM_TYPE_FUN => Fun, + ERL_NIF_TERM_TYPE_INTEGER => Integer, + ERL_NIF_TERM_TYPE_LIST => List, + ERL_NIF_TERM_TYPE_MAP => Map, + ERL_NIF_TERM_TYPE_PID => Pid, + ERL_NIF_TERM_TYPE_PORT => Port, + ERL_NIF_TERM_TYPE_REFERENCE => Ref, + ERL_NIF_TERM_TYPE_TUPLE => Tuple, + _ => Unknown, + } + } +} + pub fn get_type(term: Term) -> TermType { - if term.is_atom() { + if cfg!(nif_version_2_15) { + term.get_erl_type().into() + } else if term.is_atom() { TermType::Atom } else if term.is_binary() { TermType::Binary - } else if term.is_empty_list() { - TermType::EmptyList - } else if term.is_exception() { - TermType::Exception } else if term.is_fun() { TermType::Fun - } else if term.is_list() { + } else if term.is_list() || term.is_empty_list() { TermType::List } else if term.is_map() { TermType::Map } else if term.is_number() { - TermType::Number + TermType::Float } else if term.is_pid() { TermType::Pid } else if term.is_port() { @@ -68,7 +90,6 @@ impl<'a> Term<'a> { impl_check!(is_atom); impl_check!(is_binary); impl_check!(is_empty_list); - impl_check!(is_exception); impl_check!(is_fun); impl_check!(is_list); impl_check!(is_map); diff --git a/rustler/src/term.rs b/rustler/src/term.rs index d9a3e149..6f26d2f6 100644 --- a/rustler/src/term.rs +++ b/rustler/src/term.rs @@ -121,6 +121,11 @@ impl<'a> Term<'a> { as u32 } } + + #[cfg(feature = "nif_version_2_15")] + pub fn get_erl_type(&self) -> rustler_sys::ErlNifTermType { + unsafe { rustler_sys::enif_term_type(self.env.as_c_arg(), &self.as_c_arg()) } + } } impl<'a> PartialEq for Term<'a> { diff --git a/rustler/src/types/list.rs b/rustler/src/types/list.rs index 4dae2319..342d45f6 100644 --- a/rustler/src/types/list.rs +++ b/rustler/src/types/list.rs @@ -44,7 +44,7 @@ pub struct ListIterator<'a> { impl<'a> ListIterator<'a> { fn new(term: Term<'a>) -> Option { - if term.is_list() || term.is_empty_list() { + if term.is_list() { let iter = ListIterator { term }; Some(iter) } else { diff --git a/rustler/src/wrapper/check.rs b/rustler/src/wrapper/check.rs index b08302de..ae9883bb 100644 --- a/rustler/src/wrapper/check.rs +++ b/rustler/src/wrapper/check.rs @@ -11,7 +11,6 @@ macro_rules! impl_check_fun { impl_check_fun!(is_atom, rustler_sys::enif_is_atom); impl_check_fun!(is_binary, rustler_sys::enif_is_binary); impl_check_fun!(is_empty_list, rustler_sys::enif_is_empty_list); -impl_check_fun!(is_exception, rustler_sys::enif_is_exception); impl_check_fun!(is_fun, rustler_sys::enif_is_fun); impl_check_fun!(is_list, rustler_sys::enif_is_list); impl_check_fun!(is_map, rustler_sys::enif_is_map); diff --git a/rustler_sys/src/rustler_sys_api.rs b/rustler_sys/src/rustler_sys_api.rs index c7841a9e..ab15827b 100644 --- a/rustler_sys/src/rustler_sys_api.rs +++ b/rustler_sys/src/rustler_sys_api.rs @@ -307,6 +307,7 @@ pub enum ErlNifHash { } /// See [ErlNifTermType](http://www.erlang.org/doc/man/erl_nif.html#ErlNifTermType) in the Erlang docs. +#[cfg(feature = "nif_version_2_15")] #[derive(Copy, Clone)] #[repr(C)] pub enum ErlNifTermType {