Skip to content

feat(stable-api): Add RARRAY_AREF and RARRAY_ASET for array element access #671

@ianks

Description

@ianks

Summary

Add stable API methods for accessing and setting Ruby array elements by index, equivalent to the C macros RARRAY_AREF and RARRAY_ASET.

Motivation

Direct array element access is fundamental for:

  • Implementing array-like data structures
  • High-performance array iteration
  • Bulk array operations

The RARRAY_ASET macro is particularly important as it includes proper GC write barriers.

Ruby Source Reference

// include/ruby/internal/core/rarray.h

// Read element (currently a macro that expands to pointer access)
#define RARRAY_AREF(a, i) RARRAY_CONST_PTR(a)[i]

// Write element with GC write barrier
static inline void
RARRAY_ASET(VALUE ary, long i, VALUE v)
{
    RARRAY_PTR_USE(ary, ptr,
        RB_OBJ_WRITE(ary, &ptr[i], v));
}

Proposed API

/// Get an element from a Ruby array by index (akin to `RARRAY_AREF`).
///
/// # Safety
/// This function is unsafe because it dereferences a raw pointer and
/// does not bounds check. The caller must ensure:
/// - `obj` is a valid T_ARRAY object
/// - `idx` is within bounds (0 <= idx < RARRAY_LEN(obj))
unsafe fn rarray_aref(&self, obj: VALUE, idx: c_long) -> VALUE;

/// Set an element in a Ruby array by index (akin to `RARRAY_ASET`).
///
/// This function includes the proper GC write barrier.
///
/// # Safety
/// This function is unsafe because it:
/// - Dereferences raw pointers
/// - Modifies array contents
/// The caller must ensure:
/// - `obj` is a valid T_ARRAY object  
/// - `idx` is within bounds (0 <= idx < RARRAY_LEN(obj))
unsafe fn rarray_aset(&self, obj: VALUE, idx: c_long, val: VALUE);

Implementation Notes

  • rarray_aref: Simply rarray_const_ptr(obj).offset(idx)
  • rarray_aset: Must call rb_gc_writebarrier() or use RB_OBJ_WRITE pattern
  • This is critical for GC correctness - cannot skip the write barrier!
  • Reference: include/ruby/internal/core/rarray.h:385-403

Checklist

  • Add methods to StableApiDefinition trait
  • Implement for each Ruby version
  • Add C fallback in compiled.c
  • Add public macro wrappers in macros.rs
  • Add comprehensive tests including write barrier verification
  • Document GC safety requirements

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions