$ show danielpclark/rutie
Rutie is a Rust library that provides comprehensive bindings to the Ruby C API, enabling bidirectional integration between Rust and Ruby. It allows Rust programs to embed the Ruby VM, create and manipulate Ruby objects, define Ruby classes and modules from Rust, and wrap Rust structs as Ruby objects with garbage collection support. The architecture is layered: `rubysys` contains raw FFI declarations to Ruby's C functions, `binding` provides safe wrappers around those FFI calls, and `class` offers a high-level public API with well-documented types like `Array`, `Hash`, `RString`, `Class`, and `VM`. The library also includes powerful macros (`class!`, `methods!`, `wrappable_struct!`) that simplify defining Ruby-compatible types and methods. It is actively maintained, supports Ruby 2.7 through 3.4, and uses the `rb-sys` crate for modern Ruby compatibility. The codebase is well-structured, extensively documented with examples, and demonstrates advanced FFI patterns, though it acknowledges that some operations are unsafe due to Ruby's exception handling model.
The LLM identified 3 files worth highlighting for reuse:
The `wrappable_struct!` macro encapsulates the complexity of Ruby's typed data API, allowing Rust structs to be wrapped as Ruby objects with optional GC mark callbacks. It automatically generates a `DataTypeWrapper` implementation and a lazy-static wrapper, handling the `rb_data_type_t` structure and freeing logic. This pattern is reusable for any Rust struct that needs to be exposed to Ruby, and it demonstrates non-obvious skill in bridging Rust's ownership model with Ruby's garbage collector.
The `methods!` macro provides a safe DSL for defining Ruby method callbacks in Rust. It automatically converts arguments using `Object::try_convert_to()`, returning `Result` types that allow error handling via `map_err`. This eliminates unsafe manual argument parsing and type checking, making it easier to write robust Ruby extensions. The macro is self-contained and can be extracted to other projects that use the same `Object` trait pattern.
The `CodepointIterator` provides a Rust iterator over the codepoints of a Ruby string, respecting the string's encoding. It uses Ruby's internal `rb_enc_codepoint_len` function to correctly decode multi-byte characters. The implementation freezes the string to prevent mutation during iteration and handles pointer arithmetic safely. This is a clean, reusable pattern for processing Ruby strings in a character-aware manner, and it could be adapted to other FFI contexts that need encoding-aware iteration.