use std::panic::UnwindSafe;
use rb_sys::{ID, VALUE};
use crate::{
error::{self, raise, Error},
value::{Id, Value},
};
pub trait AsRawValue {
fn as_raw(self) -> VALUE;
}
pub trait FromRawValue {
unsafe fn from_raw(value: VALUE) -> Self;
}
impl AsRawValue for Value {
fn as_raw(self) -> VALUE {
self.as_rb_value()
}
}
impl FromRawValue for Value {
unsafe fn from_raw(val: VALUE) -> Value {
Value::new(val.into())
}
}
pub trait AsRawId {
fn as_raw(self) -> ID;
}
pub trait FromRawId {
unsafe fn from_raw(id: ID) -> Self;
}
impl AsRawId for Id {
fn as_raw(self) -> ID {
self.as_rb_id()
}
}
impl FromRawId for Id {
unsafe fn from_raw(id: ID) -> Id {
Id::new(id.into())
}
}
pub fn protect<F>(func: F) -> Result<VALUE, Error>
where
F: FnOnce() -> VALUE,
{
error::protect(|| Value::new(func())).map(|v| v.as_rb_value())
}
pub fn catch_unwind<F, T>(func: F) -> Result<T, Error>
where
F: FnOnce() -> T + UnwindSafe,
{
std::panic::catch_unwind(func).map_err(Error::from_panic)
}
pub unsafe fn resume_error(e: Error) -> ! {
raise(e)
}
#[deprecated(since = "0.4.0", note = "please use `Value::as_raw` instead")]
pub fn raw_value(val: Value) -> VALUE {
val.as_raw()
}
#[deprecated(since = "0.4.0", note = "please use `Value::from_raw` instead")]
pub unsafe fn value_from_raw(val: VALUE) -> Value {
Value::from_raw(val)
}
#[deprecated(since = "0.4.0", note = "please use `Id::as_raw` instead")]
pub fn raw_id(id: Id) -> ID {
id.as_raw()
}
#[deprecated(since = "0.4.0", note = "please use `Id::from_raw` instead")]
pub unsafe fn id_from_raw(id: ID) -> Id {
Id::from_raw(id)
}
#[cfg(test)]
mod tests {
use crate::{
class,
rb_sys::{AsRawId, FromRawId},
value::Id,
Module, RArray, RClass, Symbol,
};
#[test]
fn roundtrip_all_symbols() {
let _cleanup = unsafe { magnus::embed::init() };
let sym_class: RClass = class::object().const_get("Symbol").unwrap();
let symbols: RArray = sym_class.funcall("all_symbols", ()).unwrap();
for sym in symbols.each() {
let sym: Symbol = sym.unwrap().try_convert().unwrap();
let id: Id = sym.into();
assert_eq!(id, unsafe { Id::from_raw(id.as_raw()) });
}
}
}