use crate::{
binding::{
class::const_get,
global::{rb_cObject, RubySpecialConsts},
vm,
},
rubysys::rproc::{rb_obj_is_method, rb_obj_is_proc},
types::{c_char, c_int, c_void, Argc, InternalValue, Value},
AnyObject, Boolean, Object,
};
use std::{
ffi::{CStr, CString},
ptr, slice,
};
pub unsafe fn cstr_to_string(str: *const c_char) -> String {
CStr::from_ptr(str).to_string_lossy().into_owned()
}
pub unsafe fn cstr_to_str<'a>(str: *const c_char) -> &'a str {
CStr::from_ptr(str).to_str().unwrap()
}
pub fn str_to_cstring(str: &str) -> CString {
CString::new(str).unwrap()
}
pub fn bool_to_value(state: bool) -> Value {
let internal_value = if state {
RubySpecialConsts::True
} else {
RubySpecialConsts::False
};
Value::from(internal_value as InternalValue)
}
#[inline]
pub fn c_int_to_bool(int: c_int) -> bool {
int != 0
}
#[inline]
pub fn bool_to_c_int(state: bool) -> c_int {
state as c_int
}
pub fn arguments_to_values(arguments: &[AnyObject]) -> Vec<Value> {
arguments.as_ref().iter().map(Object::value).collect()
}
pub fn process_arguments(arguments: &[Value]) -> (Argc, *const Value) {
(arguments.len() as Argc, arguments.as_ptr())
}
pub fn option_to_slice<'a, T>(option: &'a Option<T>) -> &'a [T] {
match option {
&Some(ref v) => unsafe { slice::from_raw_parts(v, 1) },
&None => &[],
}
}
pub fn parse_arguments(argc: Argc, arguments: *const AnyObject) -> Vec<AnyObject> {
unsafe { slice::from_raw_parts(arguments, argc as usize).to_vec() }
}
pub fn closure_to_ptr<F, R>(mut func: F) -> *const c_void
where
F: FnMut() -> R,
{
let wrap_return = move || {
let r = func();
Box::into_raw(Box::new(r)) as *const c_void
};
let fnbox = Box::new(wrap_return) as Box<dyn FnMut() -> *const c_void>;
Box::into_raw(Box::new(fnbox)) as *const c_void
}
pub unsafe fn ptr_to_data<R>(ptr: *mut c_void) -> R {
*Box::from_raw(ptr as *mut R)
}
pub fn is_proc(obj: Value) -> bool {
Boolean::from(unsafe { rb_obj_is_proc(obj) }).to_bool()
}
pub fn is_method(obj: Value) -> bool {
Boolean::from(unsafe { rb_obj_is_method(obj) }).to_bool()
}
pub fn inmost_rb_object(klass: &str) -> Value {
let object = unsafe { rb_cObject };
klass.split("::").fold(object, |acc, x| const_get(acc, x))
}
pub mod callback_call {
use crate::types::{c_void, st_retval, CallbackMutPtr};
pub fn no_parameters<F: FnMut() -> R, R>(ptr: CallbackMutPtr) -> R {
let f = ptr as *mut F;
unsafe { (*f)() }
}
pub fn one_parameter<F: FnMut(A) -> R, A, R>(a: A, ptr: CallbackMutPtr) -> R {
let f = ptr as *mut F;
unsafe { (*f)(a) }
}
pub fn hash_foreach_callback<F: FnMut(A, B), A, B>(
a: A,
b: B,
ptr: CallbackMutPtr,
) -> st_retval {
let f = ptr as *mut F;
unsafe {
(*f)(a, b);
}
st_retval::Continue
}
}