diff --git a/src/lib.rs b/src/lib.rs index 95d4462..bf7e0d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -358,7 +358,7 @@ pub trait Runtime: Resource + Default { name: &str, script_data: &mut Self::ScriptData, entity: Entity, - args: impl for<'a> FuncArgs<'a, Self::Value, Self>, + args: impl for<'a> FuncArgs<'a, Self::Value, Self> + Send + 'static, ) -> Result; /// Calls a function by value defined within the runtime in the context of the diff --git a/src/runtimes/ruby.rs b/src/runtimes/ruby.rs index 9dc1f46..b351463 100644 --- a/src/runtimes/ruby.rs +++ b/src/runtimes/ruby.rs @@ -3,6 +3,7 @@ // TODO: add tests for every runtime for return value // TODO: consider dropping magnus // TODO: unwinding https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions +// TODO: maybe unify api and call non thread methods non_send use std::{ collections::HashMap, ffi::{c_void, CString}, @@ -131,10 +132,10 @@ pub struct RubyValue(magnus::value::Opaque); impl RubyValue { fn nil(ruby: &Ruby) -> Self { - Self::new(ruby.qnil().as_value(), ruby) + Self::new(ruby.qnil().as_value()) } - fn new(value: magnus::Value, ruby: &Ruby) -> Self { + fn new(value: magnus::Value) -> Self { Self(magnus::value::Opaque::from(value)) } } @@ -191,7 +192,7 @@ impl Runtime for RubyRuntime { .unwrap() .execute(Box::new(move |ruby| { let value = ruby.eval::(&script).unwrap(); - RubyValue::new(value, &ruby) + RubyValue::new(value) })); Ok(RubyScriptData) } @@ -235,7 +236,7 @@ impl Runtime for RubyRuntime { f( (), args.iter() - .map(|arg| RubyValue::new(arg.into_value(), &ruby)) + .map(|arg| RubyValue::new(arg.into_value())) .collect(), ) .expect("failed to call callback"); @@ -258,7 +259,7 @@ impl Runtime for RubyRuntime { name: &str, _script_data: &mut Self::ScriptData, _entity: bevy::prelude::Entity, - _args: impl for<'a> crate::FuncArgs<'a, Self::Value, Self>, + args: impl for<'a> crate::FuncArgs<'a, Self::Value, Self> + Send + 'static, ) -> Result { let name = name.to_string(); Ok(self @@ -266,7 +267,12 @@ impl Runtime for RubyRuntime { .as_ref() .unwrap() .execute(Box::new(move |ruby| { - let _: magnus::Value = ruby.class_object().funcall(name, ()).unwrap(); + let args: Vec<_> = args + .parse(&ruby) + .into_iter() + .map(|a| ruby.get_inner(a.0)) + .collect(); + let _: magnus::Value = ruby.class_object().funcall(name, args.as_slice()).unwrap(); RubyValue::nil(&ruby) }))) } @@ -297,8 +303,8 @@ impl FromRuntimeValueWithEngine<'_, RubyRuntime> for T { } impl IntoRuntimeValueWithEngine<'_, T, RubyRuntime> for T { - fn into_runtime_value_with_engine(value: T, engine: &magnus::Ruby) -> RubyValue { - RubyValue::new(value.into_value(), engine) + fn into_runtime_value_with_engine(value: T, _engine: &magnus::Ruby) -> RubyValue { + RubyValue::new(value.into_value()) } } @@ -308,9 +314,11 @@ impl FuncArgs<'_, RubyValue, RubyRuntime> for () { } } -impl FuncArgs<'_, RubyValue, RubyRuntime> for Vec { +impl FuncArgs<'_, RubyValue, RubyRuntime> for Vec { fn parse(self, engine: &magnus::Ruby) -> Vec { - self.into_iter().map(|_x| RubyValue::nil(engine)).collect() + self.into_iter() + .map(|x| RubyValue::new(x.into_value())) + .collect() } } diff --git a/tests/tests.rs b/tests/tests.rs index ad1a927..4991357 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -502,17 +502,28 @@ mod ruby_tests { }) } - fn assert_state_key_value_i32(_world: &World, _entity_id: Entity, _key: &str, _value: i32) { - todo!(); + fn assert_state_key_value_i32(world: &World, _entity_id: Entity, key: &str, value: i32) { + let runtime = world.get_resource::().unwrap(); + let key = key.to_string(); + runtime.with_engine_thread(move |engine| { + let state: magnus::value::Value = engine.class_object().const_get("STATE").unwrap(); + let res: i32 = state.funcall_public("[]", (key,)).unwrap(); + assert_eq!(res, value) + }) } fn assert_state_key_value_string( - _world: &World, + world: &World, _entity_id: Entity, - _key: &str, - _value: &str, + key: &str, + value: &str, ) { - todo!(); + let runtime = world.get_resource::().unwrap(); + runtime.with_engine(|engine| { + let state: magnus::value::Value = engine.class_object().const_get("STATE").unwrap(); + let res: String = state.funcall_public("[]", (key,)).unwrap(); + assert_eq!(res, value); + }); } }