Skip to content

Commit

Permalink
Use enif_get_double to implement is_float
Browse files Browse the repository at this point in the history
  • Loading branch information
filmor committed Feb 12, 2024
1 parent 81e2f30 commit 176fc5c
Showing 1 changed file with 5 additions and 34 deletions.
39 changes: 5 additions & 34 deletions rustler/src/dynamic.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ffi::c_double;

#[cfg(feature = "nif_version_2_15")]
use rustler_sys::ErlNifTermType;

Expand Down Expand Up @@ -104,40 +106,9 @@ impl<'a> Term<'a> {
impl_check!(is_tuple);

pub fn is_float(self) -> bool {
// Implementation derived from OTP's erl_nif.h, macro `is_float`. `is_number` already
// checks `is_float | is_integer`, so to distinguish these two, we check explicitly for
// float again.
const TAG_PRIMARY_MASK: usize = 0x3;
const TAG_PRIMARY_BOXED: usize = 0x2;
const TAG_PRIMARY_SIZE: usize = 2;
const TAG_PRIMARY_HEADER: usize = 0x0;
const TAG_PTR_MASK: usize = 0x7;
const FLOAT_SUBTAG: usize = 0x6 << TAG_PRIMARY_SIZE;
const TAG_HEADER_FLOAT: usize = TAG_PRIMARY_HEADER | FLOAT_SUBTAG;
const HEADER_ARITY_OFFSET: usize = 6;

const SIZE: usize = if cfg!(target_pointer_width = "64") {
// Also TAG_PTR_MASK 0x7
// TAG_LITERAL_PTR 0x4
1
} else {
2
};

const HEADER_FLONUM: usize = (SIZE << HEADER_ARITY_OFFSET) + TAG_HEADER_FLOAT;

let term_val = self.as_c_arg();
if term_val & TAG_PRIMARY_MASK == TAG_PRIMARY_BOXED {
dbg!(term_val);
let term_ptr = if cfg!(target_pointer_width = "64") {
term_val & !TAG_PTR_MASK
} else {
term_val - TAG_PRIMARY_BOXED
};
let header = unsafe { *(term_ptr as *const usize) };
header == HEADER_FLONUM
} else {
false
let mut val: c_double = 0.0;
unsafe {
rustler_sys::enif_get_double(self.get_env().as_c_arg(), self.as_c_arg(), &mut val) == 1
}
}

Expand Down

0 comments on commit 176fc5c

Please sign in to comment.