ruru 0.9.3

Native Ruby extensions in Rust
Documentation
use std::ptr;

use ruby_sys::{thread, vm};

use types::{CallbackPtr, c_int, c_void, Value};
use util;

pub fn block_proc() -> Value {
    unsafe { vm::rb_block_proc() }
}

pub fn is_block_given() -> bool {
    let result = unsafe { vm::rb_block_given_p() };

    util::c_int_to_bool(result)
}

pub fn init() {
    unsafe {
        vm::ruby_init();
    }
}

pub fn require(name: &str) {
    let name = util::str_to_cstring(name);

    unsafe {
        vm::rb_require(name.as_ptr());
    }
}

pub fn raise(exception: Value, message: &str) {
    let message = util::str_to_cstring(message);

    unsafe {
        vm::rb_raise(exception, message.as_ptr());
    }
}

pub fn thread_call_without_gvl<F, R, G>(func: F, unblock_func: Option<G>) -> R
    where F: FnOnce() -> R,
          G: FnOnce()
{
    unsafe {
        let ptr = if let Some(ubf) = unblock_func {
            thread::rb_thread_call_without_gvl(callbox as CallbackPtr,
                                               util::closure_to_ptr(func),
                                               callbox as CallbackPtr,
                                               util::closure_to_ptr(ubf))
        } else {
            thread::rb_thread_call_without_gvl(callbox as CallbackPtr,
                                               util::closure_to_ptr(func),
                                               ptr::null() as CallbackPtr,
                                               ptr::null() as *const c_void)
        };

        util::ptr_to_data(ptr)
    }
}

pub fn thread_call_without_gvl2<F, R, G>(func: F, unblock_func: Option<G>) -> R
    where F: FnOnce() -> R,
          G: FnOnce()
{
    unsafe {
        let ptr = if let Some(ubf) = unblock_func {
            thread::rb_thread_call_without_gvl2(callbox as CallbackPtr,
                                                util::closure_to_ptr(func),
                                                callbox as CallbackPtr,
                                                util::closure_to_ptr(ubf))
        } else {
            thread::rb_thread_call_without_gvl2(callbox as CallbackPtr,
                                                util::closure_to_ptr(func),
                                                ptr::null() as CallbackPtr,
                                                ptr::null() as *const c_void)
        };

        util::ptr_to_data(ptr)
    }
}

pub fn thread_call_with_gvl<F, R>(func: F) -> R
    where F: FnOnce() -> R
{
    unsafe {
        let ptr = thread::rb_thread_call_with_gvl(callbox as CallbackPtr,
                                                  util::closure_to_ptr(func));

        util::ptr_to_data(ptr)
    }

}

extern "C" fn callbox(boxptr: *mut c_void) -> *const c_void {
    let mut fnbox: Box<Box<FnMut() -> *const c_void>> =
        unsafe { Box::from_raw(boxptr as *mut Box<FnMut() -> *const c_void>) };

    fnbox()
}

pub fn protect<F>(func: F) -> Result<Value, c_int>
    where F: FnOnce()
{
    let mut state = 0;
    let value = unsafe {
        vm::rb_protect(callbox as CallbackPtr,
                       util::closure_to_ptr(func),
                       &mut state as *mut c_int)
    };
    if state == 0 { Ok(value) } else { Err(state) }
}