use crate::mruby::*;
mod array;
mod bool;
mod float;
mod hash;
mod integer;
mod option;
mod r_symbol;
mod string;
mod tuples;
mod unit;
pub use r_symbol::*;
pub type MrbResult<T> = Result<T, MrbConversionError>;
pub trait TryIntoMrb {
fn try_into_mrb(self, mrb: *mut minu_state) -> MrbResult<MrbValue>;
}
pub trait TryFromMrb<Target = Self>: Sized {
fn try_from_mrb(value: MrbValue) -> MrbResult<Target>;
}
pub trait IntoArgs {
type Output: AsRef<[minu_value]>;
fn into_args(self, mrb: *mut minu_state) -> MrbResult<Self::Output>;
}
impl IntoArgs for () {
type Output = [minu_value; 0];
fn into_args(self, _mrb: *mut minu_state) -> MrbResult<Self::Output> {
Ok([])
}
}
pub trait MrbValueLike {
fn mrb(&self) -> *mut minu_state;
fn val(&self) -> minu_value;
}
impl MrbValueLike for MrbValue {
fn mrb(&self) -> *mut minu_state {
self.mrb
}
fn val(&self) -> minu_value {
self.val
}
}
#[derive(Clone, Debug)]
pub struct MrbValue {
pub mrb: *mut minu_state,
pub val: minu_value,
}
impl MrbValue {
pub fn new(mrb: *mut minu_state, val: minu_value) -> Self {
Self { mrb, val }
}
pub fn call<ARGS: IntoArgs, RETVAL: TryFromMrb>(
&self,
name: &str,
args: ARGS,
) -> MrbResult<RETVAL> {
let args = args.into_args(self.mrb)?;
let argv = args.as_ref();
let argc = argv.len();
let mid = RSymbol::new(self.mrb, name).mid();
let val =
unsafe { minu_funcall_argv(self.mrb, self.val, mid, argc as _, argv.as_ptr() as _) };
println!("{}", unsafe {
String::try_from_mrb(MrbValue::new(self.mrb, minu_inspect(self.mrb, val)))?
});
RETVAL::try_from_mrb(Self::new(self.mrb, val))
}
}
impl TryIntoMrb for MrbValue {
fn try_into_mrb(self, _mrb: *mut minu_state) -> MrbResult<MrbValue> {
Ok(self)
}
}
impl TryFromMrb for MrbValue {
fn try_from_mrb(value: MrbValue) -> MrbResult<Self> {
Ok(value)
}
}
impl std::fmt::Display for MrbConversionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.msg)
}
}
impl std::error::Error for MrbConversionError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
#[derive(Debug)]
pub struct MrbConversionError {
pub msg: String,
}
impl MrbConversionError {
pub fn new(ty: &str) -> Self {
Self {
msg: format!("Could not convert into {}", ty),
}
}
}