Rosy

Build status Lines of code crates.io downloads docs.rs MIT or Apache 2.0

High-level, zero (or low) cost bindings of [Ruby]'s C API for [Rust].

Index

Features

Installation

This crate is available on crates.io and can be used by adding the following to your project's [Cargo.toml]:

toml [dependencies] rosy = "0.0.6"

Rosy has functionality that is only available for certain Ruby versions. The following features can currently be enabled:

For example:

toml [dependencies.rosy] version = "0.0.6" features = ["ruby_2_6"]

Finally add this to your crate root (main.rs or lib.rs):

rust extern crate rosy;

Usage

Rosy allows you to perform many operations over Ruby objects in a way that feels very natural in Rust.

```rust use rosy::String;

// The VM must be initialized before doing anything rosy::vm::init().expect("Could not initialize Ruby");

let string = String::from("hello\r\n"); string.call("chomp!").unwrap();

assert_eq!(string, "hello"); ```

Defining Ruby Methods

To define a [UTF-8]-aware method blank? on Ruby's String class, one can very simply use the [def_method!] macro. This allows for defining a function that takes the typed object (in this case String) for the class as its receiver.

```rust use rosy::prelude::*;

let class = Class::of::();

rosy::defmethod!(class, "blank?", |this: String| { this.iswhitespace() }).unwrap();

let string = String::from(" \r\n"); let result = string.call("blank?");

assert_eq!(result.unwrap(), true); ```

Although the macro may feel somewhat magical, it's actually just a zero-cost wrapper around [Class::def_method], which itself is a low-cost abstraction over rb_define_method_id. To bring the abstraction cost down to absolute zero, use [def_method_unchecked!].

Defining Ruby Classes

Defining a new class is rather straightforward:

rust let my_object = Class::def("MyObject").unwrap();

Attempting to define an existing class will result in an error:

```rust let array = Class::def("Array") .unwraperr() .existingclass() .unwrap();

assert_eq!(array, Class::array()); ```

To get an existing named class if it's not a built-in class, one should call [Class::get]:

rust let my_object = Class::get("MyObject").unwrap();

And if it's ambiguous as to whether the class already exists, there's the best of both worlds: [Class::get_or_def]. This will define a class with the given name if it doesn't already exist.

rust let my_object = Class::get_or_def("MyObject").unwrap();

To define a class within the namespace of a class or module, use [Mixin::def_class].

Defining Ruby Subclasses

The [Class::subclass] method allows for creating a new class that inherits from the method receiver's class.

```rust let subobject = myobject.subclass("MyObjectChild").unwrap();

assert!(subobject < myobject); ```

To define a subclass within the namespace of a class or module, use [Mixin::def_subclass].

Catching Ruby Exceptions

Rust code can be [protected] from Ruby exceptions very easily.

```rust use rosy::{Object, String, protected};

let string = String::from("¡Hola!");

let result = protected(|| unsafe { string.callunchecked("likespie?") });

assert!(result.unwraperr().isnomethoderror()); ```

Authors

License

This project is made available under either the conditions of the MIT License or Apache License 2.0 at your choosing.

See LICENSE.md.


Back to top