Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
80 changes: 7 additions & 73 deletions crates/rb-sys-tests/src/stable_api_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rb_sys::{stable_api, StableApiDefinition, RTYPEDDATA_EMBEDDED_P, RTYPEDDATA_P, VALUE};
use rb_sys::{stable_api, StableApiDefinition, RTYPEDDATA_P, VALUE};
use rb_sys_test_helpers::rstring as gen_rstring;

macro_rules! parity_test {
Expand Down Expand Up @@ -53,14 +53,6 @@ fn gen_typed_data() -> VALUE {
ruby_eval!("Time.now")
}

fn gen_embedded_typed_data() -> VALUE {
ruby_eval!("Time.at(0)")
}

fn gen_non_embedded_typed_data() -> VALUE {
ruby_eval!("require 'stringio'; StringIO.new('a' * 1000)")
}

parity_test!(
name: test_rstring_len_basic,
func: rstring_len,
Expand Down Expand Up @@ -677,14 +669,6 @@ parity_test! (
expected: true
);

parity_test! (
name: test_rtypeddata_embedded_p_for_typed_data,
func: rtypeddata_embedded_p,
data_factory: {
gen_typed_data()
}
);

parity_test! (
name: test_rtypeddata_type_for_typed_data,
func: rtypeddata_type,
Expand All @@ -701,68 +685,18 @@ parity_test! (
}
);

parity_test! (
name: test_rtypeddata_p_for_large_typed_data,
func: rtypeddata_p,
data_factory: {
gen_non_embedded_typed_data()
}
);

parity_test! (
name: test_rtypeddata_embedded_p_for_small_data,
func: rtypeddata_embedded_p,
data_factory: {
gen_embedded_typed_data()
}
);

parity_test! (
name: test_rtypeddata_embedded_p_for_large_data,
func: rtypeddata_embedded_p,
data_factory: {
gen_non_embedded_typed_data()
}
);

parity_test! (
name: test_rtypeddata_get_data_for_small_data,
func: rtypeddata_get_data,
data_factory: {
gen_embedded_typed_data()
}
);

parity_test! (
name: test_rtypeddata_get_data_for_large_data,
func: rtypeddata_get_data,
data_factory: {
gen_non_embedded_typed_data()
}
);

#[rb_sys_test_helpers::ruby_test]
fn test_rtypeddata_functions_with_usage() {
let small_time = gen_embedded_typed_data();
let large_time = gen_non_embedded_typed_data();
let obj = gen_typed_data();

unsafe {
for obj in [small_time, large_time].iter() {
assert!(RTYPEDDATA_P(*obj));

let type_ptr = stable_api::get_default().rtypeddata_type(*obj);
assert!(!type_ptr.is_null());

let data_ptr = stable_api::get_default().rtypeddata_get_data(*obj);
assert!(!data_ptr.is_null());
}
assert!(RTYPEDDATA_P(obj));

let _small_embedded = RTYPEDDATA_EMBEDDED_P(small_time);
let large_embedded = RTYPEDDATA_EMBEDDED_P(large_time);
let type_ptr = stable_api::get_default().rtypeddata_type(obj);
assert!(!type_ptr.is_null());

#[cfg(ruby_gte_3_3)]
assert!(_small_embedded);
assert!(!large_embedded);
let data_ptr = stable_api::get_default().rtypeddata_get_data(obj);
assert!(!data_ptr.is_null());
}
}

Expand Down
15 changes: 0 additions & 15 deletions crates/rb-sys/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,21 +301,6 @@ pub unsafe fn RTYPEDDATA_P(obj: VALUE) -> bool {
api().rtypeddata_p(obj)
}

/// Checks if the given RTypedData is embedded.
///
/// @param[in] obj An RTypedData object.
/// @retval true The data is embedded in the object itself.
/// @retval false The data is stored separately.
///
/// # Safety
/// This function is unsafe because it could dereference a raw pointer when
/// accessing the underlying data structure. The caller must ensure the object
/// is a valid RTypedData.
#[inline(always)]
pub unsafe fn RTYPEDDATA_EMBEDDED_P(obj: VALUE) -> bool {
api().rtypeddata_embedded_p(obj)
}

/// Gets the data type information from an RTypedData object.
///
/// @param[in] obj An RTypedData object.
Expand Down
8 changes: 0 additions & 8 deletions crates/rb-sys/src/stable_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,6 @@ pub trait StableApiDefinition {
/// is valid and points to a T_DATA object.
unsafe fn rtypeddata_p(&self, obj: VALUE) -> bool;

/// Checks if the given RTypedData is embedded.
///
/// # Safety
/// This function is unsafe because it dereferences a raw pointer to get
/// access to underlying Ruby data. The caller must ensure that the pointer
/// is valid and points to an RTypedData object.
unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool;

/// Gets the data type from an RTypedData object.
///
/// # Safety
Expand Down
10 changes: 0 additions & 10 deletions crates/rb-sys/src/stable_api/compiled.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,6 @@ int impl_rtypeddata_p(VALUE obj)
return RTYPEDDATA_P(obj);
}

int impl_rtypeddata_embedded_p(VALUE obj)
{
#if RUBY_VERSION_AT_LEAST_3_3
return RTYPEDDATA_EMBEDDED_P(obj);
#else
// On Ruby versions before 3.3, embedded typed data is not supported
return 0;
#endif
}

const struct rb_data_type_struct *
impl_rtypeddata_type(VALUE obj)
{
Expand Down
15 changes: 0 additions & 15 deletions crates/rb-sys/src/stable_api/compiled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@ extern "C" {
#[link_name = "impl_rtypeddata_p"]
fn impl_rtypeddata_p(obj: VALUE) -> bool;

#[link_name = "impl_rtypeddata_embedded_p"]
fn impl_rtypeddata_embedded_p(obj: VALUE) -> bool;

#[link_name = "impl_rtypeddata_type"]
fn impl_rtypeddata_type(obj: VALUE) -> *const crate::rb_data_type_t;

Expand Down Expand Up @@ -268,18 +265,6 @@ impl StableApiDefinition for Definition {
impl_rtypeddata_p(obj)
}

#[inline]
#[cfg(ruby_gte_3_3)]
unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool {
impl_rtypeddata_embedded_p(obj)
}

#[inline]
#[cfg(ruby_lt_3_3)]
unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool {
false
}

#[inline]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
impl_rtypeddata_type(obj)
Expand Down
6 changes: 0 additions & 6 deletions crates/rb-sys/src/stable_api/ruby_2_7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,6 @@ impl StableApiDefinition for Definition {
typed_flag == 1
}

#[inline]
unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool {
// Ruby 2.7 doesn't support embedded data
false
}

#[inline]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand Down
6 changes: 0 additions & 6 deletions crates/rb-sys/src/stable_api/ruby_3_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,6 @@ impl StableApiDefinition for Definition {
typed_flag == 1
}

#[inline]
unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool {
// Ruby 3.0 and lower don't support embedded data
false
}

#[inline]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand Down
6 changes: 0 additions & 6 deletions crates/rb-sys/src/stable_api/ruby_3_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,6 @@ impl StableApiDefinition for Definition {
typed_flag == 1
}

#[inline]
unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool {
// Ruby 3.1 and lower don't support embedded data
false
}

#[inline]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand Down
6 changes: 0 additions & 6 deletions crates/rb-sys/src/stable_api/ruby_3_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,6 @@ impl StableApiDefinition for Definition {
typed_flag == 1
}

#[inline]
unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool {
// Ruby 3.2 and lower don't support embedded data
false
}

#[inline]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand Down
27 changes: 8 additions & 19 deletions crates/rb-sys/src/stable_api/ruby_3_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,24 +282,6 @@ impl StableApiDefinition for Definition {
typed_flag != 0 && typed_flag <= 3
}

#[inline]
unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool {
debug_ruby_assert_type!(
obj,
RUBY_T_DATA,
"rtypeddata_embedded_p called on non-T_DATA object"
);

let rdata = obj as *const crate::internal::RTypedData;
let typed_flag = (*rdata).typed_flag;
#[cfg(target_pointer_width = "64")]
const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64;
#[cfg(target_pointer_width = "32")]
const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32;

(typed_flag & FLAG) != 0
}

#[inline]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand All @@ -320,7 +302,14 @@ impl StableApiDefinition for Definition {
"rtypeddata_get_data called on non-T_DATA object"
);

if self.rtypeddata_embedded_p(obj) {
let rdata = obj as *const crate::internal::RTypedData;
let typed_flag = (*rdata).typed_flag;
#[cfg(target_pointer_width = "64")]
const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64;
#[cfg(target_pointer_width = "32")]
const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32;

if (typed_flag & FLAG) != 0 {
// For embedded data, calculate pointer based on struct layout
// The formula matches Ruby's implementation:
// embedded_typed_data_size = sizeof(RTypedData) - sizeof(void *)
Expand Down
27 changes: 8 additions & 19 deletions crates/rb-sys/src/stable_api/ruby_3_4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,24 +297,6 @@ impl StableApiDefinition for Definition {
typed_flag != 0 && typed_flag <= 3
}

#[inline(always)]
unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool {
debug_ruby_assert_type!(
obj,
RUBY_T_DATA,
"rtypeddata_embedded_p called on non-T_DATA object"
);

let rdata = obj as *const RTypedData;
let typed_flag = (*rdata).typed_flag;
#[cfg(target_pointer_width = "64")]
const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64;
#[cfg(target_pointer_width = "32")]
const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32;

(typed_flag & FLAG) != 0
}

#[inline(always)]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand All @@ -335,7 +317,14 @@ impl StableApiDefinition for Definition {
"rtypeddata_get_data called on non-T_DATA object"
);

if self.rtypeddata_embedded_p(obj) {
let rdata = obj as *const RTypedData;
let typed_flag = (*rdata).typed_flag;
#[cfg(target_pointer_width = "64")]
const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64;
#[cfg(target_pointer_width = "32")]
const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32;

if (typed_flag & FLAG) != 0 {
// For embedded data, calculate pointer based on struct layout
// The formula matches Ruby's implementation:
// embedded_typed_data_size = sizeof(RTypedData) - sizeof(void *)
Expand Down
17 changes: 3 additions & 14 deletions crates/rb-sys/src/stable_api/ruby_4_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,19 +295,6 @@ impl StableApiDefinition for Definition {
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USERPRIV0 as VALUE) != 0
}

#[inline(always)]
unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool {
debug_ruby_assert_type!(
obj,
RUBY_T_DATA,
"rtypeddata_embedded_p called on non-T_DATA object"
);

// Ruby 4.0: TYPED_DATA_EMBEDDED is bit 0 of the type field
let rdata = obj as *const RTypedData;
((*rdata).type_ & 1) != 0
}

#[inline(always)]
unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t {
debug_ruby_assert_type!(
Expand All @@ -330,7 +317,9 @@ impl StableApiDefinition for Definition {
"rtypeddata_get_data called on non-T_DATA object"
);

if self.rtypeddata_embedded_p(obj) {
// Ruby 4.0: TYPED_DATA_EMBEDDED is bit 0 of the type field
let rdata = obj as *const RTypedData;
if ((*rdata).type_ & 1) != 0 {
// For embedded data, calculate pointer based on struct layout
// The formula matches Ruby's implementation:
// embedded_typed_data_size = sizeof(RTypedData) - sizeof(void *)
Expand Down
6 changes: 0 additions & 6 deletions script/show-asm
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,6 @@ FUNCTIONS = [
c: {expr: "RTYPEDDATA_P(v)", ret: "int"},
ruby_source: "include/ruby/internal/core/rtypeddata.h:RTYPEDDATA_P"
},
{
name: "rtypeddata_embedded_p",
rust: {unsafe: true, ret: "bool", expr: "rb_sys::RTYPEDDATA_EMBEDDED_P(v)"},
c: {expr: "RTYPEDDATA_EMBEDDED_P(v)", ret: "int"},
ruby_source: "include/ruby/internal/core/rtypeddata.h:RTYPEDDATA_EMBEDDED_P"
},
{
name: "rtypeddata_type",
rust: {unsafe: true, ret: "*const rb_sys::rb_data_type_t", expr: "rb_sys::RTYPEDDATA_TYPE(v)"},
Expand Down
Loading