diff --git a/crates/rb-sys-build/src/bindings.rs b/crates/rb-sys-build/src/bindings.rs index 59e785f4..cd48e6e3 100644 --- a/crates/rb-sys-build/src/bindings.rs +++ b/crates/rb-sys-build/src/bindings.rs @@ -68,9 +68,7 @@ pub fn generate( let bindings = if cfg!(feature = "bindgen-deprecated-types") { bindings } else { - bindings - .blocklist_item("^ruby_fl_type.*") - .blocklist_item("^_bindgen_ty_9.*") + bindings.blocklist_item("^_bindgen_ty_9.*") }; let bindings = opaqueify_bindings(rbconfig, bindings, &mut wrapper_h); diff --git a/crates/rb-sys-tests/src/stable_api_test.rs b/crates/rb-sys-tests/src/stable_api_test.rs index 93cb078d..f639f88e 100644 --- a/crates/rb-sys-tests/src/stable_api_test.rs +++ b/crates/rb-sys-tests/src/stable_api_test.rs @@ -213,6 +213,60 @@ parity_test!( } ); +parity_test!( + name: test_bignum_positive_p_evaled, + func: bignum_positive_p, + data_factory: { + ruby_eval!("2 ** 64") + }, + expected: true +); + +parity_test!( + name: test_bignum_negative_p_evaled, + func: bignum_negative_p, + data_factory: { + ruby_eval!("-(2 ** 64)") + }, + expected: true +); + +parity_test!( + name: test_bignum_positive_p_for_zero, + func: bignum_positive_p, + data_factory: { + unsafe { rb_sys::rb_int2big(0) } + }, + expected: true +); + +parity_test!( + name: test_bignum_negative_p_for_zero, + func: bignum_negative_p, + data_factory: { + unsafe { rb_sys::rb_int2big(0) } + }, + expected: false +); + +parity_test!( + name: test_bignum_positive_p, + func: bignum_positive_p, + data_factory: { + unsafe { rb_sys::rb_int2big(64) } + }, + expected: true +); + +parity_test!( + name: test_bignum_negative_p, + func: bignum_negative_p, + data_factory: { + unsafe { rb_sys::rb_int2big(-1) } + }, + expected: true +); + parity_test!( name: test_builtin_type_for_string, func: builtin_type, diff --git a/crates/rb-sys/src/stable_api.rs b/crates/rb-sys/src/stable_api.rs index d97204da..fe3b0cb8 100644 --- a/crates/rb-sys/src/stable_api.rs +++ b/crates/rb-sys/src/stable_api.rs @@ -54,6 +54,24 @@ pub trait StableApiDefinition { /// is valid. unsafe fn rarray_const_ptr(&self, obj: VALUE) -> *const VALUE; + /// Tests if a bignum is positive. + /// + /// # Safety + /// This function is unsafe because it dereferences a raw pointer to get + /// access to underlying RBasic struct. The caller must ensure that the + /// `VALUE` is a valid pointer to a bignum. + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool; + + /// Tests if a bignum is negative. + /// + /// # Safety + /// This function is unsafe because it dereferences a raw pointer to get + /// access to underlying RBasic struct. The caller must ensure that the + /// `VALUE` is a valid pointer to a bignum. + unsafe fn bignum_negative_p(&self, obj: VALUE) -> bool { + !self.bignum_positive_p(obj) + } + /// Tests if the given value is a special constant. fn special_const_p(&self, value: VALUE) -> bool; diff --git a/crates/rb-sys/src/stable_api/compiled.c b/crates/rb-sys/src/stable_api/compiled.c index a877f7cd..739f6634 100644 --- a/crates/rb-sys/src/stable_api/compiled.c +++ b/crates/rb-sys/src/stable_api/compiled.c @@ -25,6 +25,17 @@ impl_special_const_p(VALUE obj) { return SPECIAL_CONST_P(obj); } +int +impl_bignum_positive_p(VALUE obj) { + return RBIGNUM_POSITIVE_P(obj); +} + +int +impl_bignum_negative_p(VALUE obj) { + return RBIGNUM_NEGATIVE_P(obj); +} + + enum ruby_value_type impl_builtin_type(VALUE obj) { return RB_BUILTIN_TYPE(obj); diff --git a/crates/rb-sys/src/stable_api/compiled.rs b/crates/rb-sys/src/stable_api/compiled.rs index 418cb836..c142e7c2 100644 --- a/crates/rb-sys/src/stable_api/compiled.rs +++ b/crates/rb-sys/src/stable_api/compiled.rs @@ -19,6 +19,12 @@ extern "C" { #[link_name = "impl_special_const_p"] fn impl_special_const_p(value: VALUE) -> bool; + #[link_name = "impl_bignum_positive_p"] + fn impl_bignum_positive_p(obj: VALUE) -> bool; + + #[link_name = "impl_bignum_negative_p"] + fn impl_bignum_negative_p(obj: VALUE) -> bool; + #[link_name = "impl_builtin_type"] fn impl_builtin_type(obj: VALUE) -> ruby_value_type; @@ -93,6 +99,16 @@ impl StableApiDefinition for Definition { unsafe { impl_special_const_p(value) } } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + impl_bignum_positive_p(obj) + } + + #[inline] + unsafe fn bignum_negative_p(&self, obj: VALUE) -> bool { + impl_bignum_negative_p(obj) + } + #[inline] unsafe fn builtin_type(&self, obj: VALUE) -> ruby_value_type { impl_builtin_type(obj) diff --git a/crates/rb-sys/src/stable_api/ruby_2_6.rs b/crates/rb-sys/src/stable_api/ruby_2_6.rs index 408f096a..a36e85be 100644 --- a/crates/rb-sys/src/stable_api/ruby_2_6.rs +++ b/crates/rb-sys/src/stable_api/ruby_2_6.rs @@ -88,6 +88,13 @@ impl StableApiDefinition for Definition { ptr } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] fn special_const_p(&self, value: VALUE) -> bool { let is_immediate = value & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0; diff --git a/crates/rb-sys/src/stable_api/ruby_2_7.rs b/crates/rb-sys/src/stable_api/ruby_2_7.rs index b9ef5225..f228c7c3 100644 --- a/crates/rb-sys/src/stable_api/ruby_2_7.rs +++ b/crates/rb-sys/src/stable_api/ruby_2_7.rs @@ -88,6 +88,13 @@ impl StableApiDefinition for Definition { ptr } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] fn special_const_p(&self, value: VALUE) -> bool { let is_immediate = value & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0; diff --git a/crates/rb-sys/src/stable_api/ruby_3_0.rs b/crates/rb-sys/src/stable_api/ruby_3_0.rs index c2eb0bf0..cc059f91 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_0.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_0.rs @@ -96,6 +96,13 @@ impl StableApiDefinition for Definition { } } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] fn special_const_p(&self, value: VALUE) -> bool { let is_immediate = value & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0; diff --git a/crates/rb-sys/src/stable_api/ruby_3_1.rs b/crates/rb-sys/src/stable_api/ruby_3_1.rs index 646fa5a3..e6b747e0 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_1.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_1.rs @@ -89,6 +89,13 @@ impl StableApiDefinition for Definition { ret } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] fn special_const_p(&self, value: VALUE) -> bool { let is_immediate = value & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0; diff --git a/crates/rb-sys/src/stable_api/ruby_3_2.rs b/crates/rb-sys/src/stable_api/ruby_3_2.rs index 763158ae..c6f66e5f 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_2.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_2.rs @@ -83,6 +83,13 @@ impl StableApiDefinition for Definition { ptr } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] fn special_const_p(&self, value: VALUE) -> bool { let is_immediate = (value) & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0; diff --git a/crates/rb-sys/src/stable_api/ruby_3_3.rs b/crates/rb-sys/src/stable_api/ruby_3_3.rs index 11afd1cd..d4bd09fa 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_3.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_3.rs @@ -76,6 +76,13 @@ impl StableApiDefinition for Definition { ptr } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] fn special_const_p(&self, value: VALUE) -> bool { let is_immediate = (value) & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0; diff --git a/crates/rb-sys/src/stable_api/ruby_3_4.rs b/crates/rb-sys/src/stable_api/ruby_3_4.rs index 9cd51405..a4a9f7dc 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_4.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_4.rs @@ -84,6 +84,13 @@ impl StableApiDefinition for Definition { is_immediate || !test } + #[inline] + unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool { + let rbasic = obj as *const crate::RBasic; + + ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USER1 as VALUE) != 0 + } + #[inline] unsafe fn builtin_type(&self, obj: VALUE) -> crate::ruby_value_type { let rbasic = obj as *const crate::RBasic;