Skip to content

feat(stable-api): Add FIX2LONG, LONG2FIX for Fixnum conversions #667

@ianks

Description

@ianks

Summary

Add stable API methods for converting between Fixnum VALUEs and C long integers, equivalent to the C macros FIX2LONG, FIX2ULONG, LONG2FIX, etc.

Motivation

Fixnum conversion is one of the most common operations in Ruby C extensions. The macros are simple bit shifts but having them in the stable API ensures:

  • Consistent behavior across Ruby versions
  • No need for users to understand the internal representation
  • Type safety through Rust's type system

Proposed API

/// Convert a Fixnum VALUE to a long (akin to `FIX2LONG`).
///
/// # Safety
/// The caller must ensure the VALUE is actually a Fixnum (use FIXNUM_P first).
#[inline(always)]
fn fix2long(&self, obj: VALUE) -> c_long;

/// Convert a Fixnum VALUE to an unsigned long (akin to `FIX2ULONG`).
///
/// # Safety  
/// The caller must ensure the VALUE is actually a Fixnum.
#[inline(always)]
fn fix2ulong(&self, obj: VALUE) -> c_ulong;

/// Convert a long to a Fixnum VALUE (akin to `LONG2FIX`).
///
/// # Note
/// This does NOT check if the value fits in a Fixnum range.
/// Use `rb_int2inum` for arbitrary integers.
#[inline(always)]
fn long2fix(&self, val: c_long) -> VALUE;

/// Convert an unsigned long to a Fixnum VALUE (akin to `ULONG2NUM`).
#[inline(always)]
fn ulong2num(&self, val: c_ulong) -> VALUE;

/// Check if a long fits in a Fixnum (akin to `FIXABLE`).
#[inline(always)]
fn fixable(&self, val: c_long) -> bool;

/// Check if an unsigned long fits in a Fixnum (akin to `POSFIXABLE`).
#[inline(always)]
fn posfixable(&self, val: c_ulong) -> bool;

Implementation Notes

  • Fixnum uses tagged pointers: (val << 1) | 1
  • Range is approximately -(2^62) to (2^62 - 1) on 64-bit
  • These are simple bit operations, very fast
  • Reference: include/ruby/internal/arithmetic/fixnum.h

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 edge cases
  • Add to show-asm script for performance verification

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