1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
//! Definitions for Ruby's special constants.
//!
//! Makes it easier to reference important Ruby constants, without havign to dig
//! around in bindgen's output.
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
use std::convert::TryInto;
use crate::{
ruby_value_type::{self, RUBY_T_MASK},
Qfalse, Qnil, Qtrue, Qundef, RBasic, FIXNUM_P, FLONUM_P, SPECIAL_CONST_P, STATIC_SYM_P, VALUE,
};
pub use ruby_value_type::*;
/// Queries the type of the object.
///
/// @param[in] obj Object in question.
/// @pre `obj` must not be a special constant.
/// @return The type of `obj`.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// attemping to access the underlying [`RBasic`] struct.
#[inline(always)]
pub unsafe fn RB_BUILTIN_TYPE(obj: VALUE) -> ruby_value_type {
debug_assert!(!SPECIAL_CONST_P(obj));
let rbasic = obj as *const RBasic;
let ret = (*rbasic).flags & RUBY_T_MASK as VALUE;
let ret: u32 = ret.try_into().unwrap();
std::mem::transmute::<_, ruby_value_type>(ret)
}
/// Queries if the object is an instance of ::rb_cInteger.
///
/// @param[in] obj Object in question.
/// @retval true It is.
/// @retval false It isn't.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// attemping to access the underlying [`RBasic`] struct.
#[inline(always)]
pub unsafe fn RB_INTEGER_TYPE_P(obj: VALUE) -> bool {
if FIXNUM_P(obj) {
true
} else if SPECIAL_CONST_P(obj) {
false
} else {
RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM
}
}
/// Queries if the object is a dynamic symbol.
///
/// @param[in] obj Object in question.
/// @retval true It is.
/// @retval false It isn't.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// attemping to access the underlying [`RBasic`] struct.
#[inline(always)]
pub unsafe fn RB_DYNAMIC_SYM_P(obj: VALUE) -> bool {
if SPECIAL_CONST_P(obj) {
false
} else {
RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL
}
}
/// Queries if the object is an instance of ::rb_cSymbol.
///
/// @param[in] obj Object in question.
/// @retval true It is.
/// @retval false It isn't.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// attemping to access the underlying [`RBasic`] struct.
#[inline(always)]
pub unsafe fn RB_SYMBOL_P(obj: VALUE) -> bool {
STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj)
}
/// Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
///
/// @param[in] obj Object in question.
/// @return The type of `obj`.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// attemping to access the underlying [`RBasic`] struct.
#[inline(always)]
pub unsafe fn RB_TYPE_P<T: Into<VALUE>>(value: T) -> ruby_value_type {
let obj = value.into();
if !SPECIAL_CONST_P(obj) {
RB_BUILTIN_TYPE(obj)
} else if obj == Qfalse as VALUE {
RUBY_T_FALSE
} else if obj == Qnil as VALUE {
RUBY_T_NIL
} else if obj == Qtrue as VALUE {
RUBY_T_TRUE
} else if obj == Qundef as VALUE {
RUBY_T_UNDEF
} else if FIXNUM_P(obj) {
RUBY_T_FIXNUM
} else if STATIC_SYM_P(obj) {
RUBY_T_SYMBOL
} else {
debug_assert!(FLONUM_P(obj));
RUBY_T_FLOAT
}
}
/// Queries if the object is an instance of ::rb_cFloat.
///
/// @param[in] obj Object in question.
/// @retval true It is.
/// @retval false It isn't.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// attemping to access the underlying [`RBasic`] struct.
pub unsafe fn RB_FLOAT_TYPE_P(obj: VALUE) -> bool {
if FLONUM_P(obj) {
true
} else if SPECIAL_CONST_P(obj) {
false
} else {
RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT
}
}