From d32c138e996ec2fe17b7a5f7c0d3ff1562e446f0 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Mon, 19 Feb 2024 17:57:19 -0500 Subject: [PATCH] Implement lua types for usize, make userdata field setter and getters return results --- src/lib.rs | 26 ++++++++++++++++ src/tests.rs | 14 ++++++--- src/userdata/builder.rs | 55 +++++++++++++++++++++++++++++----- src/value.rs | 66 +++++++++++++---------------------------- 4 files changed, 104 insertions(+), 57 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ca6aba4..b0bc496 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,7 @@ impl_as_lua_number!(u8); impl_as_lua_number!(u16); impl_as_lua_number!(u32); impl_as_lua_number!(u64); +impl_as_lua_number!(usize); impl_as_lua_number!(f32); impl_as_lua_number!(f64); @@ -141,4 +142,29 @@ impl<'a> PushToLuaStack<'a> for &str { Ok(()) } +} + +impl<'a> AsLua<'a> for bool { + fn as_lua(self, _lua: &'a State) -> crate::Result> { + Ok(Value::Boolean(self)) + } +} + +impl<'a> FromLua<'a> for bool { + fn from_lua(_lua: &State, val: Value) -> crate::Result { + match val { + Value::Boolean(v) => Ok(v), + _ => Err(Error::type_mismatch( + "Boolean", + &val.type_name(), + )), + } + } +} + +impl<'a> PushToLuaStack<'a> for bool { + unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> { + let v = self.as_lua(state)?; + v.push_to_lua_stack(state) + } } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 29da7b9..769028f 100755 --- a/src/tests.rs +++ b/src/tests.rs @@ -10,10 +10,16 @@ pub struct Vec2 { impl Userdata for Vec2 { fn build<'a>(_state: &State, builder: &mut UserdataBuilder<'a, Vec2>) -> crate::Result<()> { builder - .field_getter("x", |_, this| this.x) - .field_getter("y", |_, this| this.y) - .field_setter("x", |_, this, x: f32| this.x = x) - .field_setter("y", |_, this, y: f32| this.y = y) + .field_getter("x", |_, this| Ok(this.x)) + .field_getter("y", |_, this| Ok(this.y)) + .field_setter("x", |_, this, x: f32| { + this.x = x; + Ok(()) + }) + .field_setter("y", |_, this, y: f32| { + this.y = y; + Ok(()) + }) .function("new", |lua, (x, y)| lua.create_userdata(Vec2 { x, y })) // method test .method("add", |lua, lhs: &Vec2, (rhs,): (Ref,)| { diff --git a/src/userdata/builder.rs b/src/userdata/builder.rs index 9a4e586..d9fe45c 100755 --- a/src/userdata/builder.rs +++ b/src/userdata/builder.rs @@ -8,6 +8,7 @@ pub type UserdataMutGetterFn<'a> = Arc) -> c pub struct UserdataBuilder<'a, T> { pub(crate) name: String, + pub(crate) field_consts: HashMap>, pub(crate) field_getters: HashMap>, pub(crate) field_setters: HashMap>, pub(crate) functions: HashMap>, @@ -23,6 +24,7 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> { pub fn new() -> Self { Self { name: T::name(), + field_consts: HashMap::new(), field_getters: HashMap::new(), field_setters: HashMap::new(), functions: HashMap::new(), @@ -33,13 +35,14 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> { } } - pub fn field_getter(&mut self, name: &str, f: F) -> &mut Self + pub fn field(&mut self, name: &str, f: R) -> &mut Self where - F: Fn(&'a State, &T) -> R + 'static, + //F: Fn(&'a State) -> R + 'static, R: AsLua<'a>, - T: Userdata + 'static + //T: Userdata + 'static { - let wrapped = self.wrapped_getter.clone(); + todo!() + /* let wrapped = self.wrapped_getter.clone(); let wrapped: Arc) -> Result<*const (), crate::Error>>>> = unsafe { mem::transmute(wrapped) }; let ud_name = self.name.clone(); @@ -68,12 +71,50 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> { }; self.field_getters.insert(name.to_string(), Box::new(wrap)); + self */ + } + + pub fn field_getter(&mut self, name: &str, f: F) -> &mut Self + where + F: Fn(&'a State, &T) -> crate::Result + 'static, + R: AsLua<'a>, + T: Userdata + 'static + { + let wrapped = self.wrapped_getter.clone(); + let wrapped: Arc) -> Result<*const (), crate::Error>>>> = unsafe { mem::transmute(wrapped) }; + + let ud_name = self.name.clone(); + let fn_name = name.to_string(); + + let wrap = move |lua: &'a State, mut val: ValueVec<'a>| { + let val = val.pop_front().unwrap(); + let this = val.as_userdata().unwrap(); // if this panics, its a bug + + if let Some(getter) = wrapped.get() { + let this_ptr = Self::result_to_bad_arg( + getter(this.clone()), + &ud_name, + &fn_name, + 1, + Some("self") + )?; + let this_ptr = this_ptr.cast::(); + let this = unsafe { &*this_ptr }; + + f(lua, this)?.as_lua(lua) + } else { + let this = this.as_ref::()?; + f(lua, &*this)?.as_lua(lua) + } + }; + self.field_getters.insert(name.to_string(), Box::new(wrap)); + self } pub fn field_setter(&mut self, name: &str, f: F) -> &mut Self where - F: Fn(&'a State, &mut T, V) -> () + 'static, + F: Fn(&'a State, &mut T, V) -> crate::Result<()> + 'static, V: FromLua<'a>, T: Userdata + 'static { @@ -101,11 +142,11 @@ impl<'a, T: Userdata> UserdataBuilder<'a, T> { let this_ptr = this_ptr.cast::(); let this = unsafe { this_ptr.as_mut().unwrap() }; - f(lua, this, v_arg).as_lua(lua) + f(lua, this, v_arg)?.as_lua(lua) } else { let mut this = this.as_mut::()?; - f(lua, this.deref_mut(), v_arg).as_lua(lua) + f(lua, this.deref_mut(), v_arg)?.as_lua(lua) } }; self.field_setters.insert(name.to_string(), Box::new(wrap)); diff --git a/src/value.rs b/src/value.rs index 7a2d800..0b87801 100755 --- a/src/value.rs +++ b/src/value.rs @@ -417,23 +417,6 @@ impl<'a> IntoLuaVec<'a> for ValueVec<'a> { } } -/* impl<'a> FromLua<'a> for ValueVec<'a> { - fn from_lua(_lua: &'a State, val: Value<'a>) -> crate::Result { - match val { - Value::Variable(v) => Ok(v), - _ => { - Ok(ValueVec::from(val)) - } - } - } -} */ - -/* impl<'a> FromLuaVec<'a> for ValueVec<'a> { - fn from_lua_value_vec(_state: &'a State, values: ValueVec<'a>) -> crate::Result { - Ok(values) - } -} */ - impl<'a> PushToLuaStack<'a> for ValueVec<'a> { unsafe fn push_to_lua_stack(&self, state: &'a State) -> crate::Result<()> { for v in self.iter() { @@ -465,13 +448,6 @@ macro_rules! impl_from_lua_vec_for_from_lua { Some(1) } } - - - /* impl<'a> IntoLuaVec<'a> for $type<'a> { - fn into_lua_value_vec(self, state: &'a State) -> crate::Result> { - Ok(ValueVec::from(self.as_lua(state)?)) - } - } */ }; ($type: tt) => { impl<'a> FromLuaVec<'a> for $type { @@ -490,16 +466,11 @@ macro_rules! impl_from_lua_vec_for_from_lua { Some(1) } } - - /* impl<'a> IntoLuaVec<'a> for $type { - fn into_lua_value_vec(self, state: &'a State) -> crate::Result> { - Ok(ValueVec::from(self.as_lua(state)?)) - } - } */ }; } impl_from_lua_vec_for_from_lua!(i64); +impl_from_lua_vec_for_from_lua!(usize); impl_from_lua_vec_for_from_lua!(u64); impl_from_lua_vec_for_from_lua!(i16); impl_from_lua_vec_for_from_lua!(u16); @@ -516,16 +487,6 @@ impl_from_lua_vec_for_from_lua!(Value, 'a); impl_from_lua_vec_for_from_lua!(Function, 'a); impl_from_lua_vec_for_from_lua!(AnyUserdata, 'a); -/* impl<'a, T: FromLua<'a>> FromLuaVec<'a> for T { - fn from_lua_value_vec(state: &'a State, mut values: ValueVec<'a>) -> crate::Result { - if let Some(v) = values.pop_front() { - Ok(T::from_lua(state, v)?) - } else { - Err(Error::Nil) - } - } -} */ - impl<'a, T: AsLua<'a>> IntoLuaVec<'a> for T { fn into_lua_value_vec(self, state: &'a State) -> crate::Result> { let mut v = ValueVec::new(); @@ -607,12 +568,6 @@ impl<'a> FromLuaVec<'a> for () { } } -/* impl<'a> IntoLuaVec<'a> for () { - fn into_lua_value_vec(self, _state: &'a State) -> crate::Result> { - Ok(ValueVec::new()) - } -} */ - macro_rules! impl_from_lua_vec_tuple { ( $count: expr, $last: tt, $( $name: tt ),+ ) => ( #[allow(non_snake_case)] @@ -709,3 +664,22 @@ macro_rules! impl_from_lua_vec_tuple { // hopefully 16 is more than enough // if you have 16 function results, and need more than 16, you NEED help impl_from_lua_vec_tuple! { 16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16 } + +impl<'a, T: AsLua<'a>, const N: usize> AsLua<'a> for [T; N] { + fn as_lua(self, lua: &'a State) -> crate::Result> { + let table = lua.create_table()?; + + for (idx, t) in self.into_iter().enumerate() { + table.set(idx + 1, t)?; + } + + Ok(Value::Table(table)) + } +} + +// TODO: Find out a way to implement this +/* impl<'a, T: FromLua> FromLuaVec<'a> for T { + fn from_lua_value_vec(state: &'a State, values: ValueVec<'a>) -> crate::Result { + todo!() + } +} */ \ No newline at end of file