diff --git a/src/lua.rs b/src/lua.rs index 5acab41..2b0cdf4 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -29,7 +29,7 @@ use crate::types::{ Callback, CallbackUpvalue, DestructedUserdata, Integer, LightUserData, LuaRef, MaybeSend, Number, RegistryKey, }; -use crate::userdata::{AnyUserData, UserData, UserDataCell}; +use crate::userdata::{AnyUserData, MetaMethod, UserData, UserDataCell}; use crate::userdata_impl::{StaticUserDataFields, StaticUserDataMethods, UserDataProxy}; use crate::util::{ self, assert_stack, callback_error, check_stack, get_destructed_userdata_metatable, @@ -2515,16 +2515,16 @@ impl Lua { push_table(state, 0, metatable_nrec as c_int, true)?; for (k, m) in methods.meta_methods { self.push_value(Value::Function(self.create_callback(m)?))?; - rawset_field(state, -2, k.validate()?.name())?; + rawset_field(state, -2, MetaMethod::validate(&k)?)?; } #[cfg(feature = "async")] for (k, m) in methods.async_meta_methods { self.push_value(Value::Function(self.create_async_callback(m)?))?; - rawset_field(state, -2, k.validate()?.name())?; + rawset_field(state, -2, MetaMethod::validate(&k)?)?; } for (k, f) in fields.meta_fields { self.push_value(f(self)?)?; - rawset_field(state, -2, k.validate()?.name())?; + rawset_field(state, -2, MetaMethod::validate(&k)?)?; } let metatable_index = ffi::lua_absindex(state, -1); diff --git a/src/scope.rs b/src/scope.rs index b603e4a..48a8bd1 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -371,11 +371,11 @@ impl<'lua, 'scope> Scope<'lua, 'scope> { for (k, m) in ud_methods.meta_methods { let data = data.clone(); lua.push_value(Value::Function(wrap_method(self, data, ud_ptr, m)?))?; - rawset_field(state, -2, k.validate()?.name())?; + rawset_field(state, -2, MetaMethod::validate(&k)?)?; } for (k, f) in ud_fields.meta_fields { lua.push_value(f(mem::transmute(lua))?)?; - rawset_field(state, -2, k.validate()?.name())?; + rawset_field(state, -2, MetaMethod::validate(&k)?)?; } let metatable_index = ffi::lua_absindex(state, -1); @@ -611,7 +611,7 @@ enum NonStaticMethod<'lua, T> { struct NonStaticUserDataMethods<'lua, T: UserData> { methods: Vec<(String, NonStaticMethod<'lua, T>)>, - meta_methods: Vec<(MetaMethod, NonStaticMethod<'lua, T>)>, + meta_methods: Vec<(String, NonStaticMethod<'lua, T>)>, } impl<'lua, T: UserData> Default for NonStaticUserDataMethods<'lua, T> { @@ -624,170 +624,154 @@ impl<'lua, T: UserData> Default for NonStaticUserDataMethods<'lua, T> { } impl<'lua, T: UserData> UserDataMethods<'lua, T> for NonStaticUserDataMethods<'lua, T> { - fn add_method(&mut self, name: &str, method: M) + fn add_method(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, { - self.methods.push(( - name.into(), - NonStaticMethod::Method(Box::new(move |lua, ud, args| { - method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let method = NonStaticMethod::Method(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.methods.push((name.as_ref().into(), method)); } - fn add_method_mut(&mut self, name: &str, mut method: M) + fn add_method_mut(&mut self, name: impl AsRef, mut method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, { - self.methods.push(( - name.into(), - NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { - method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let method = NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.methods.push((name.as_ref().into(), method)); } #[cfg(feature = "async")] - fn add_async_method(&mut self, _name: &str, _method: M) + fn add_async_method(&mut self, _name: impl AsRef, _method: M) where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + MR: Future> + 'lua, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>, { // The panic should never happen as async non-static code wouldn't compile // Non-static lifetime must be bounded to 'lua lifetime - mlua_panic!("asynchronous methods are not supported for non-static userdata") + panic!("asynchronous methods are not supported for non-static userdata") } - fn add_function(&mut self, name: &str, function: F) + fn add_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, { - self.methods.push(( - name.into(), - NonStaticMethod::Function(Box::new(move |lua, args| { - function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let func = NonStaticMethod::Function(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.methods.push((name.as_ref().into(), func)); } - fn add_function_mut(&mut self, name: &str, mut function: F) + fn add_function_mut(&mut self, name: impl AsRef, mut function: F) where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, { - self.methods.push(( - name.into(), - NonStaticMethod::FunctionMut(Box::new(move |lua, args| { - function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let func = NonStaticMethod::FunctionMut(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.methods.push((name.as_ref().into(), func)); } #[cfg(feature = "async")] - fn add_async_function(&mut self, _name: &str, _function: F) + fn add_async_function(&mut self, _name: impl AsRef, _function: F) where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + FR: Future> + 'lua, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>, { // The panic should never happen as async non-static code wouldn't compile // Non-static lifetime must be bounded to 'lua lifetime - mlua_panic!("asynchronous functions are not supported for non-static userdata") + panic!("asynchronous functions are not supported for non-static userdata") } - fn add_meta_method(&mut self, meta: impl Into, method: M) + fn add_meta_method(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, { - self.meta_methods.push(( - meta.into(), - NonStaticMethod::Method(Box::new(move |lua, ud, args| { - method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let method = NonStaticMethod::Method(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.meta_methods.push((name.as_ref().into(), method)); } - fn add_meta_method_mut(&mut self, meta: impl Into, mut method: M) + fn add_meta_method_mut(&mut self, name: impl AsRef, mut method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, { - self.meta_methods.push(( - meta.into(), - NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { - method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let method = NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.meta_methods.push((name.as_ref().into(), method)); } #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))] - fn add_async_meta_method(&mut self, _meta: impl Into, _method: M) + fn add_async_meta_method(&mut self, _name: impl AsRef, _method: M) where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + MR: Future> + 'lua, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>, { // The panic should never happen as async non-static code wouldn't compile // Non-static lifetime must be bounded to 'lua lifetime - mlua_panic!("asynchronous meta methods are not supported for non-static userdata") + panic!("asynchronous meta methods are not supported for non-static userdata") } - fn add_meta_function(&mut self, meta: impl Into, function: F) + fn add_meta_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, { - self.meta_methods.push(( - meta.into(), - NonStaticMethod::Function(Box::new(move |lua, args| { - function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let func = NonStaticMethod::Function(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.meta_methods.push((name.as_ref().into(), func)); } - fn add_meta_function_mut(&mut self, meta: impl Into, mut function: F) + fn add_meta_function_mut(&mut self, name: impl AsRef, mut function: F) where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, { - self.meta_methods.push(( - meta.into(), - NonStaticMethod::FunctionMut(Box::new(move |lua, args| { - function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let func = NonStaticMethod::FunctionMut(Box::new(move |lua, args| { + function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.meta_methods.push((name.as_ref().into(), func)); } #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))] - fn add_async_meta_function(&mut self, _meta: impl Into, _function: F) + fn add_async_meta_function(&mut self, _name: impl AsRef, _function: F) where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + FR: Future> + 'lua, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>, { // The panic should never happen as async non-static code wouldn't compile // Non-static lifetime must be bounded to 'lua lifetime - mlua_panic!("asynchronous meta functions are not supported for non-static userdata") + panic!("asynchronous meta functions are not supported for non-static userdata") } } @@ -795,7 +779,7 @@ struct NonStaticUserDataFields<'lua, T: UserData> { field_getters: Vec<(String, NonStaticMethod<'lua, T>)>, field_setters: Vec<(String, NonStaticMethod<'lua, T>)>, #[allow(clippy::type_complexity)] - meta_fields: Vec<(MetaMethod, Box Result>>)>, + meta_fields: Vec<(String, Box Result>>)>, } impl<'lua, T: UserData> Default for NonStaticUserDataFields<'lua, T> { @@ -809,75 +793,67 @@ impl<'lua, T: UserData> Default for NonStaticUserDataFields<'lua, T> { } impl<'lua, T: UserData> UserDataFields<'lua, T> for NonStaticUserDataFields<'lua, T> { - fn add_field_method_get(&mut self, name: &str, method: M) + fn add_field_method_get(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T) -> Result + MaybeSend + 'static, R: IntoLua<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result, { - self.field_getters.push(( - name.into(), - NonStaticMethod::Method(Box::new(move |lua, ud, _| { - method(lua, ud)?.into_lua_multi(lua) - })), - )); + let method = NonStaticMethod::Method(Box::new(move |lua, ud, _| { + method(lua, ud)?.into_lua_multi(lua) + })); + self.field_getters.push((name.as_ref().into(), method)); } - fn add_field_method_set(&mut self, name: &str, mut method: M) + fn add_field_method_set(&mut self, name: impl AsRef, mut method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result<()> + MaybeSend + 'static, A: FromLua<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<()>, { - self.field_setters.push(( - name.into(), - NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { - method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let method = NonStaticMethod::MethodMut(Box::new(move |lua, ud, args| { + method(lua, ud, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.field_setters.push((name.as_ref().into(), method)); } - fn add_field_function_get(&mut self, name: &str, function: F) + fn add_field_function_get(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result + MaybeSend + 'static, R: IntoLua<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result, { - self.field_getters.push(( - name.into(), - NonStaticMethod::Function(Box::new(move |lua, args| { - function(lua, AnyUserData::from_lua_multi(args, lua)?)?.into_lua_multi(lua) - })), - )); + let func = NonStaticMethod::Function(Box::new(move |lua, args| { + function(lua, AnyUserData::from_lua_multi(args, lua)?)?.into_lua_multi(lua) + })); + self.field_getters.push((name.as_ref().into(), func)); } - fn add_field_function_set(&mut self, name: &str, mut function: F) + fn add_field_function_set(&mut self, name: impl AsRef, mut function: F) where + F: FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()> + MaybeSend + 'static, A: FromLua<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()>, { - self.field_setters.push(( - name.into(), - NonStaticMethod::FunctionMut(Box::new(move |lua, args| { - let (ud, val) = <_>::from_lua_multi(args, lua)?; - function(lua, ud, val)?.into_lua_multi(lua) - })), - )); + let func = NonStaticMethod::FunctionMut(Box::new(move |lua, args| { + let (ud, val) = <_>::from_lua_multi(args, lua)?; + function(lua, ud, val)?.into_lua_multi(lua) + })); + self.field_setters.push((name.as_ref().into(), func)); } - fn add_meta_field_with(&mut self, meta: impl Into, f: F) + fn add_meta_field_with(&mut self, name: impl AsRef, f: F) where - F: 'static + MaybeSend + Fn(&'lua Lua) -> Result, + F: Fn(&'lua Lua) -> Result + MaybeSend + 'static, R: IntoLua<'lua>, { - let meta = meta.into(); + let name = name.as_ref().to_string(); self.meta_fields.push(( - meta.clone(), + name.clone(), Box::new(move |lua| { let value = f(lua)?.into_lua(lua)?; - if meta == MetaMethod::Index || meta == MetaMethod::NewIndex { + if name == MetaMethod::Index || name == MetaMethod::NewIndex { match value { Value::Nil | Value::Table(_) | Value::Function(_) => {} _ => { return Err(Error::MetaMethodTypeError { - method: meta.to_string(), + method: name.clone(), type_name: value.type_name(), message: Some("expected nil, table or function".to_string()), }) diff --git a/src/userdata.rs b/src/userdata.rs index c2275fb..c5312fb 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -1,7 +1,7 @@ use std::any::TypeId; use std::cell::{Ref, RefCell, RefMut}; use std::fmt; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::ops::{Deref, DerefMut}; use std::os::raw::{c_char, c_int}; use std::string::String as StdString; @@ -36,7 +36,7 @@ pub(crate) const USER_VALUE_MAXSLOT: usize = 8; /// generally no need to do so: [`UserData`] implementors can instead just implement `Drop`. /// /// [`UserData`]: crate::UserData -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MetaMethod { /// The `+` operator. Add, @@ -141,23 +141,17 @@ pub enum MetaMethod { /// [lua_doc]: https://www.lua.org/manual/5.4/manual.html#3.3.8 #[cfg(any(feature = "lua54"))] Close, - /// A custom metamethod. - /// - /// Must not be in the protected list: `__gc`, `__metatable`, `__mlua*`. - Custom(StdString), } -impl PartialEq for MetaMethod { - fn eq(&self, other: &Self) -> bool { - self.name() == other.name() +impl PartialEq for &str { + fn eq(&self, other: &MetaMethod) -> bool { + *self == other.name() } } -impl Eq for MetaMethod {} - -impl Hash for MetaMethod { - fn hash(&self, state: &mut H) { - self.name().hash(state); +impl PartialEq for String { + fn eq(&self, other: &MetaMethod) -> bool { + self == other.name() } } @@ -169,7 +163,7 @@ impl fmt::Display for MetaMethod { impl MetaMethod { /// Returns Lua metamethod name, usually prefixed by two underscores. - pub fn name(&self) -> &str { + pub const fn name(self) -> &'static str { match self { MetaMethod::Add => "__add", MetaMethod::Sub => "__sub", @@ -218,84 +212,22 @@ impl MetaMethod { #[cfg(feature = "lua54")] MetaMethod::Close => "__close", - - MetaMethod::Custom(ref name) => name, } } - pub(crate) fn validate(self) -> Result { - match self { - MetaMethod::Custom(name) if name == "__gc" => Err(Error::MetaMethodRestricted(name)), - MetaMethod::Custom(name) if name == "__metatable" => { - Err(Error::MetaMethodRestricted(name)) - } - MetaMethod::Custom(name) if name.starts_with("__mlua") => { - Err(Error::MetaMethodRestricted(name)) - } - _ => Ok(self), + pub(crate) fn validate(name: &str) -> Result<&str> { + match name { + "__gc" => Err(Error::MetaMethodRestricted(name.to_string())), + "__metatable" => Err(Error::MetaMethodRestricted(name.to_string())), + _ if name.starts_with("__mlua") => Err(Error::MetaMethodRestricted(name.to_string())), + name => Ok(name), } } } -impl From for MetaMethod { - fn from(name: StdString) -> Self { - match name.as_str() { - "__add" => MetaMethod::Add, - "__sub" => MetaMethod::Sub, - "__mul" => MetaMethod::Mul, - "__div" => MetaMethod::Div, - "__mod" => MetaMethod::Mod, - "__pow" => MetaMethod::Pow, - "__unm" => MetaMethod::Unm, - - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__idiv" => MetaMethod::IDiv, - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__band" => MetaMethod::BAnd, - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__bor" => MetaMethod::BOr, - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__bxor" => MetaMethod::BXor, - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__bnot" => MetaMethod::BNot, - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__shl" => MetaMethod::Shl, - #[cfg(any(feature = "lua54", feature = "lua53"))] - "__shr" => MetaMethod::Shr, - - "__concat" => MetaMethod::Concat, - "__len" => MetaMethod::Len, - "__eq" => MetaMethod::Eq, - "__lt" => MetaMethod::Lt, - "__le" => MetaMethod::Le, - "__index" => MetaMethod::Index, - "__newindex" => MetaMethod::NewIndex, - "__call" => MetaMethod::Call, - "__tostring" => MetaMethod::ToString, - - #[cfg(any( - feature = "lua54", - feature = "lua53", - feature = "lua52", - feature = "luajit52" - ))] - "__pairs" => MetaMethod::Pairs, - #[cfg(any(feature = "lua52", feature = "luajit52"))] - "__ipairs" => MetaMethod::IPairs, - #[cfg(feature = "luau")] - "__iter" => MetaMethod::Iter, - - #[cfg(feature = "lua54")] - "__close" => MetaMethod::Close, - - _ => MetaMethod::Custom(name), - } - } -} - -impl From<&str> for MetaMethod { - fn from(name: &str) -> Self { - MetaMethod::from(name.to_owned()) +impl AsRef for MetaMethod { + fn as_ref(&self) -> &str { + self.name() } } @@ -310,22 +242,22 @@ pub trait UserDataMethods<'lua, T: UserData> { /// /// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will /// be used as a fall-back if no regular method is found. - fn add_method(&mut self, name: &str, method: M) + fn add_method(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add a regular method which accepts a `&mut T` as the first parameter. /// /// Refer to [`add_method`] for more information about the implementation. /// /// [`add_method`]: #method.add_method - fn add_method_mut(&mut self, name: &str, method: M) + fn add_method_mut(&mut self, name: impl AsRef, method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add an async method which accepts a `T` as the first parameter and returns Future. /// The passed `T` is cloned from the original value. @@ -337,13 +269,13 @@ pub trait UserDataMethods<'lua, T: UserData> { /// [`add_method`]: #method.add_method #[cfg(feature = "async")] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] - fn add_async_method(&mut self, name: &str, method: M) + fn add_async_method(&mut self, name: impl AsRef, method: M) where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>; + MR: Future> + 'lua, + R: IntoLuaMulti<'lua>; /// Add a regular method as a function which accepts generic arguments, the first argument will /// be a [`AnyUserData`] of type `T` if the method is called with Lua method syntax: @@ -355,22 +287,22 @@ pub trait UserDataMethods<'lua, T: UserData> { /// [`AnyUserData`]: crate::AnyUserData /// [`add_method`]: #method.add_method /// [`add_method_mut`]: #method.add_method_mut - fn add_function(&mut self, name: &str, function: F) + fn add_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add a regular method as a mutable function which accepts generic arguments. /// /// This is a version of [`add_function`] that accepts a FnMut argument. /// /// [`add_function`]: #method.add_function - fn add_function_mut(&mut self, name: &str, function: F) + fn add_function_mut(&mut self, name: impl AsRef, function: F) where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add a regular method as an async function which accepts generic arguments /// and returns Future. @@ -382,12 +314,12 @@ pub trait UserDataMethods<'lua, T: UserData> { /// [`add_function`]: #method.add_function #[cfg(feature = "async")] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] - fn add_async_function(&mut self, name: &str, function: F) + fn add_async_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>; + FR: Future> + 'lua, + R: IntoLuaMulti<'lua>; /// Add a metamethod which accepts a `&T` as the first parameter. /// @@ -397,11 +329,11 @@ pub trait UserDataMethods<'lua, T: UserData> { /// side has a metatable. To prevent this, use [`add_meta_function`]. /// /// [`add_meta_function`]: #method.add_meta_function - fn add_meta_method(&mut self, meta: impl Into, method: M) + fn add_meta_method(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add a metamethod as a function which accepts a `&mut T` as the first parameter. /// @@ -411,11 +343,11 @@ pub trait UserDataMethods<'lua, T: UserData> { /// side has a metatable. To prevent this, use [`add_meta_function`]. /// /// [`add_meta_function`]: #method.add_meta_function - fn add_meta_method_mut(&mut self, meta: impl Into, method: M) + fn add_meta_method_mut(&mut self, name: impl AsRef, method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add an async metamethod which accepts a `T` as the first parameter and returns Future. /// The passed `T` is cloned from the original value. @@ -427,35 +359,35 @@ pub trait UserDataMethods<'lua, T: UserData> { /// [`add_meta_method`]: #method.add_meta_method #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] - fn add_async_meta_method(&mut self, name: impl Into, method: M) + fn add_async_meta_method(&mut self, name: impl AsRef, method: M) where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>; + MR: Future> + 'lua, + R: IntoLuaMulti<'lua>; /// Add a metamethod which accepts generic arguments. /// /// Metamethods for binary operators can be triggered if either the left or right argument to /// the binary operator has a metatable, so the first argument here is not necessarily a /// userdata of type `T`. - fn add_meta_function(&mut self, meta: impl Into, function: F) + fn add_meta_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add a metamethod as a mutable function which accepts generic arguments. /// /// This is a version of [`add_meta_function`] that accepts a FnMut argument. /// /// [`add_meta_function`]: #method.add_meta_function - fn add_meta_function_mut(&mut self, meta: impl Into, function: F) + fn add_meta_function_mut(&mut self, name: impl AsRef, function: F) where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result; + R: IntoLuaMulti<'lua>; /// Add a metamethod which accepts generic arguments and returns Future. /// @@ -466,12 +398,12 @@ pub trait UserDataMethods<'lua, T: UserData> { /// [`add_meta_function`]: #method.add_meta_function #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))] #[cfg_attr(docsrs, doc(cfg(feature = "async")))] - fn add_async_meta_function(&mut self, name: impl Into, function: F) + fn add_async_meta_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>; + FR: Future> + 'lua, + R: IntoLuaMulti<'lua>; // // Below are internal methods used in generated code @@ -485,16 +417,11 @@ pub trait UserDataMethods<'lua, T: UserData> { fn add_async_callback(&mut self, _name: String, _callback: AsyncCallback<'lua, 'static>) {} #[doc(hidden)] - fn add_meta_callback(&mut self, _meta: MetaMethod, _callback: Callback<'lua, 'static>) {} + fn add_meta_callback(&mut self, _name: String, _callback: Callback<'lua, 'static>) {} #[doc(hidden)] #[cfg(feature = "async")] - fn add_async_meta_callback( - &mut self, - _meta: MetaMethod, - _callback: AsyncCallback<'lua, 'static>, - ) { - } + fn add_async_meta_callback(&mut self, _name: String, _callback: AsyncCallback<'lua, 'static>) {} } /// Field registry for [`UserData`] implementors. @@ -508,10 +435,10 @@ pub trait UserDataFields<'lua, T: UserData> { /// /// If `add_meta_method` is used to set the `__index` metamethod, the `__index` metamethod will /// be used as a fall-back if no regular field or method are found. - fn add_field_method_get(&mut self, name: &str, method: M) + fn add_field_method_get(&mut self, name: impl AsRef, method: M) where - R: IntoLua<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result; + M: Fn(&'lua Lua, &T) -> Result + MaybeSend + 'static, + R: IntoLua<'lua>; /// Add a regular field setter as a method which accepts a `&mut T` as the first parameter. /// @@ -520,10 +447,10 @@ pub trait UserDataFields<'lua, T: UserData> { /// /// If `add_meta_method` is used to set the `__newindex` metamethod, the `__newindex` metamethod will /// be used as a fall-back if no regular field is found. - fn add_field_method_set(&mut self, name: &str, method: M) + fn add_field_method_set(&mut self, name: impl AsRef, method: M) where - A: FromLua<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<()>; + M: FnMut(&'lua Lua, &mut T, A) -> Result<()> + MaybeSend + 'static, + A: FromLua<'lua>; /// Add a regular field getter as a function which accepts a generic [`AnyUserData`] of type `T` /// argument. @@ -532,10 +459,10 @@ pub trait UserDataFields<'lua, T: UserData> { /// /// [`AnyUserData`]: crate::AnyUserData /// [`add_field_method_get`]: #method.add_field_method_get - fn add_field_function_get(&mut self, name: &str, function: F) + fn add_field_function_get(&mut self, name: impl AsRef, function: F) where - R: IntoLua<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result; + F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result + MaybeSend + 'static, + R: IntoLua<'lua>; /// Add a regular field setter as a function which accepts a generic [`AnyUserData`] of type `T` /// first argument. @@ -544,10 +471,10 @@ pub trait UserDataFields<'lua, T: UserData> { /// /// [`AnyUserData`]: crate::AnyUserData /// [`add_field_method_set`]: #method.add_field_method_set - fn add_field_function_set(&mut self, name: &str, function: F) + fn add_field_function_set(&mut self, name: impl AsRef, function: F) where - A: FromLua<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()>; + F: FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()> + MaybeSend + 'static, + A: FromLua<'lua>; /// Add a metamethod value computed from `f`. /// @@ -557,10 +484,10 @@ pub trait UserDataFields<'lua, T: UserData> { /// /// `mlua` will trigger an error on an attempt to define a protected metamethod, /// like `__gc` or `__metatable`. - fn add_meta_field_with(&mut self, meta: impl Into, f: F) + fn add_meta_field_with(&mut self, name: impl AsRef, f: F) where - R: IntoLua<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua) -> Result; + F: Fn(&'lua Lua) -> Result + MaybeSend + 'static, + R: IntoLua<'lua>; // // Below are internal methods used in generated code @@ -642,10 +569,12 @@ pub trait UserDataFields<'lua, T: UserData> { /// [`UserDataMethods`]: crate::UserDataMethods pub trait UserData: Sized { /// Adds custom fields specific to this userdata. - fn add_fields<'lua, F: UserDataFields<'lua, Self>>(_fields: &mut F) {} + #[allow(unused_variables)] + fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {} /// Adds custom methods and operators specific to this userdata. - fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(_methods: &mut M) {} + #[allow(unused_variables)] + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {} } // Wraps UserData in a way to always implement `serde::Serialize` trait. @@ -661,7 +590,7 @@ impl UserDataCell { #[inline] pub(crate) fn new_ser(data: T) -> Self where - T: 'static + Serialize, + T: Serialize + 'static, { UserDataCell(RefCell::new(UserDataWrapped::new_ser(data))) } @@ -686,7 +615,7 @@ impl UserDataCell { // Consumes this `UserDataCell`, returning the wrapped value. #[inline] - fn into_inner(self) -> T { + unsafe fn into_inner(self) -> T { self.0.into_inner().into_inner() } } @@ -707,17 +636,17 @@ impl UserDataWrapped { #[inline] fn new_ser(data: T) -> Self where - T: 'static + Serialize, + T: Serialize + 'static, { UserDataWrapped::Serializable(Box::new(data)) } #[inline] - fn into_inner(self) -> T { + unsafe fn into_inner(self) -> T { match self { Self::Default(data) => *data, #[cfg(feature = "serialize")] - Self::Serializable(data) => unsafe { *Box::from_raw(Box::into_raw(data) as *mut T) }, + Self::Serializable(data) => *Box::from_raw(Box::into_raw(data) as *mut T), } } } @@ -796,7 +725,7 @@ impl OwnedAnyUserData { impl<'lua> AnyUserData<'lua> { /// Checks whether the type of this userdata is `T`. - pub fn is(&self) -> bool { + pub fn is(&self) -> bool { match self.inspect(|_: &UserDataCell| Ok(())) { Ok(()) => true, Err(Error::UserDataTypeMismatch) => false, @@ -811,7 +740,7 @@ impl<'lua> AnyUserData<'lua> { /// Returns a `UserDataBorrowError` if the userdata is already mutably borrowed. Returns a /// `UserDataTypeMismatch` if the userdata is not of type `T`. #[inline] - pub fn borrow(&self) -> Result> { + pub fn borrow(&self) -> Result> { self.inspect(|cell| cell.try_borrow()) } @@ -822,7 +751,7 @@ impl<'lua> AnyUserData<'lua> { /// Returns a `UserDataBorrowMutError` if the userdata cannot be mutably borrowed. /// Returns a `UserDataTypeMismatch` if the userdata is not of type `T`. #[inline] - pub fn borrow_mut(&self) -> Result> { + pub fn borrow_mut(&self) -> Result> { self.inspect(|cell| cell.try_borrow_mut()) } @@ -830,7 +759,7 @@ impl<'lua> AnyUserData<'lua> { /// Sets the special "destructed" metatable that prevents any further operations with this userdata. /// /// Keeps associated user values unchanged (they will be collected by Lua's GC). - pub fn take(&self) -> Result { + pub fn take(&self) -> Result { let lua = self.0.lua; let state = lua.state(); unsafe { @@ -980,12 +909,13 @@ impl<'lua> AnyUserData<'lua> { /// The value can be retrieved with [`get_named_user_value`]. /// /// [`get_named_user_value`]: #method.get_named_user_value - pub fn set_named_user_value(&self, name: &str, v: V) -> Result<()> + pub fn set_named_user_value(&self, name: impl AsRef, v: V) -> Result<()> where V: IntoLua<'lua>, { let lua = self.0.lua; let state = lua.state(); + let name = name.as_ref(); unsafe { let _sg = StackGuard::new(state); check_stack(state, 5)?; @@ -1018,12 +948,13 @@ impl<'lua> AnyUserData<'lua> { /// Returns an associated value by name set by [`set_named_user_value`]. /// /// [`set_named_user_value`]: #method.set_named_user_value - pub fn get_named_user_value(&self, name: &str) -> Result + pub fn get_named_user_value(&self, name: impl AsRef) -> Result where V: FromLua<'lua>, { let lua = self.0.lua; let state = lua.state(); + let name = name.as_ref(); unsafe { let _sg = StackGuard::new(state); check_stack(state, 4)?; @@ -1098,9 +1029,9 @@ impl<'lua> AnyUserData<'lua> { Ok(false) } - fn inspect<'a, T, R, F>(&'a self, func: F) -> Result + fn inspect<'a, T, F, R>(&'a self, func: F) -> Result where - T: 'static + UserData, + T: UserData + 'static, F: FnOnce(&'a UserDataCell) -> Result, { let lua = self.0.lua; @@ -1149,8 +1080,8 @@ impl<'lua> UserDataMetatable<'lua> { /// /// If no value is associated to `key`, returns the `Nil` value. /// Access to restricted metamethods such as `__gc` or `__metatable` will cause an error. - pub fn get, V: FromLua<'lua>>(&self, key: K) -> Result { - self.0.raw_get(key.into().validate()?.name()) + pub fn get>(&self, key: impl AsRef) -> Result { + self.0.raw_get(MetaMethod::validate(key.as_ref())?) } /// Sets a key-value pair in the metatable. @@ -1159,18 +1090,18 @@ impl<'lua> UserDataMetatable<'lua> { /// Access to restricted metamethods such as `__gc` or `__metatable` will cause an error. /// Setting `__index` or `__newindex` metamethods is also restricted because their values are cached /// for `mlua` internal usage. - pub fn set, V: IntoLua<'lua>>(&self, key: K, value: V) -> Result<()> { - let key = key.into().validate()?; + pub fn set>(&self, key: impl AsRef, value: V) -> Result<()> { + let key = MetaMethod::validate(key.as_ref())?; // `__index` and `__newindex` cannot be changed in runtime, because values are cached if key == MetaMethod::Index || key == MetaMethod::NewIndex { return Err(Error::MetaMethodRestricted(key.to_string())); } - self.0.raw_set(key.name(), value) + self.0.raw_set(key, value) } /// Checks whether the metatable contains a non-nil value for `key`. - pub fn contains>(&self, key: K) -> Result { - self.0.contains_key(key.into().validate()?.name()) + pub fn contains(&self, key: impl AsRef) -> Result { + self.0.contains_key(MetaMethod::validate(key.as_ref())?) } /// Consumes this metatable and returns an iterator over the pairs of the metatable. @@ -1197,15 +1128,15 @@ impl<'lua, V> Iterator for UserDataMetatablePairs<'lua, V> where V: FromLua<'lua>, { - type Item = Result<(MetaMethod, V)>; + type Item = Result<(String, V)>; fn next(&mut self) -> Option { loop { match self.0.next()? { Ok((key, value)) => { // Skip restricted metamethods - if let Ok(metamethod) = MetaMethod::from(key).validate() { - break Some(Ok((metamethod, value))); + if MetaMethod::validate(&key).is_ok() { + break Some(Ok((key, value))); } } Err(e) => break Some(Err(e)), diff --git a/src/userdata_impl.rs b/src/userdata_impl.rs index aad6be6..5ed7242 100644 --- a/src/userdata_impl.rs +++ b/src/userdata_impl.rs @@ -19,21 +19,21 @@ use std::rc::Rc; #[cfg(feature = "async")] use { crate::types::AsyncCallback, - futures_core::future::Future, futures_util::future::{self, TryFutureExt}, + std::future::Future, }; -pub(crate) struct StaticUserDataMethods<'lua, T: 'static + UserData> { +pub(crate) struct StaticUserDataMethods<'lua, T: UserData + 'static> { pub(crate) methods: Vec<(String, Callback<'lua, 'static>)>, #[cfg(feature = "async")] pub(crate) async_methods: Vec<(String, AsyncCallback<'lua, 'static>)>, - pub(crate) meta_methods: Vec<(MetaMethod, Callback<'lua, 'static>)>, + pub(crate) meta_methods: Vec<(String, Callback<'lua, 'static>)>, #[cfg(feature = "async")] - pub(crate) async_meta_methods: Vec<(MetaMethod, AsyncCallback<'lua, 'static>)>, + pub(crate) async_meta_methods: Vec<(String, AsyncCallback<'lua, 'static>)>, _type: PhantomData, } -impl<'lua, T: 'static + UserData> Default for StaticUserDataMethods<'lua, T> { +impl<'lua, T: UserData + 'static> Default for StaticUserDataMethods<'lua, T> { fn default() -> StaticUserDataMethods<'lua, T> { StaticUserDataMethods { methods: Vec::new(), @@ -47,134 +47,135 @@ impl<'lua, T: 'static + UserData> Default for StaticUserDataMethods<'lua, T> { } } -impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMethods<'lua, T> { - fn add_method(&mut self, name: &str, method: M) +impl<'lua, T: UserData + 'static> UserDataMethods<'lua, T> for StaticUserDataMethods<'lua, T> { + fn add_method(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, - { - self.methods.push((name.into(), Self::box_method(method))); - } - - fn add_method_mut(&mut self, name: &str, method: M) - where - A: FromLuaMulti<'lua>, - R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, { self.methods - .push((name.into(), Self::box_method_mut(method))); + .push((name.as_ref().into(), Self::box_method(method))); + } + + fn add_method_mut(&mut self, name: impl AsRef, method: M) + where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, + A: FromLuaMulti<'lua>, + R: IntoLuaMulti<'lua>, + { + self.methods + .push((name.as_ref().into(), Self::box_method_mut(method))); } #[cfg(feature = "async")] - fn add_async_method(&mut self, name: &str, method: M) + fn add_async_method(&mut self, name: impl AsRef, method: M) where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + MR: Future> + 'lua, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>, { self.async_methods - .push((name.into(), Self::box_async_method(method))); + .push((name.as_ref().into(), Self::box_async_method(method))); } - fn add_function(&mut self, name: &str, function: F) + fn add_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, { self.methods - .push((name.into(), Self::box_function(function))); + .push((name.as_ref().into(), Self::box_function(function))); } - fn add_function_mut(&mut self, name: &str, function: F) + fn add_function_mut(&mut self, name: impl AsRef, function: F) where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, { self.methods - .push((name.into(), Self::box_function_mut(function))); + .push((name.as_ref().into(), Self::box_function_mut(function))); } #[cfg(feature = "async")] - fn add_async_function(&mut self, name: &str, function: F) + fn add_async_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + FR: Future> + 'lua, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>, { self.async_methods - .push((name.into(), Self::box_async_function(function))); + .push((name.as_ref().into(), Self::box_async_function(function))); } - fn add_meta_method(&mut self, meta: impl Into, method: M) + fn add_meta_method(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, { self.meta_methods - .push((meta.into(), Self::box_method(method))); + .push((name.as_ref().into(), Self::box_method(method))); } - fn add_meta_method_mut(&mut self, meta: impl Into, method: M) + fn add_meta_method_mut(&mut self, name: impl AsRef, method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, { self.meta_methods - .push((meta.into(), Self::box_method_mut(method))); + .push((name.as_ref().into(), Self::box_method_mut(method))); } #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))] - fn add_async_meta_method(&mut self, meta: impl Into, method: M) + fn add_async_meta_method(&mut self, name: impl AsRef, method: M) where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + MR: Future> + 'lua, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>, { self.async_meta_methods - .push((meta.into(), Self::box_async_method(method))); + .push((name.as_ref().into(), Self::box_async_method(method))); } - fn add_meta_function(&mut self, meta: impl Into, function: F) + fn add_meta_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, { self.meta_methods - .push((meta.into(), Self::box_function(function))); + .push((name.as_ref().into(), Self::box_function(function))); } - fn add_meta_function_mut(&mut self, meta: impl Into, function: F) + fn add_meta_function_mut(&mut self, name: impl AsRef, function: F) where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, { self.meta_methods - .push((meta.into(), Self::box_function_mut(function))); + .push((name.as_ref().into(), Self::box_function_mut(function))); } #[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))] - fn add_async_meta_function(&mut self, meta: impl Into, function: F) + fn add_async_meta_function(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + FR: Future> + 'lua, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>, { self.async_meta_methods - .push((meta.into(), Self::box_async_function(function))); + .push((name.as_ref().into(), Self::box_async_function(function))); } // Below are internal methods used in generated code @@ -188,26 +189,22 @@ impl<'lua, T: 'static + UserData> UserDataMethods<'lua, T> for StaticUserDataMet self.async_methods.push((name, callback)); } - fn add_meta_callback(&mut self, meta: MetaMethod, callback: Callback<'lua, 'static>) { - self.meta_methods.push((meta, callback)); + fn add_meta_callback(&mut self, name: String, callback: Callback<'lua, 'static>) { + self.meta_methods.push((name, callback)); } #[cfg(feature = "async")] - fn add_async_meta_callback( - &mut self, - meta: MetaMethod, - callback: AsyncCallback<'lua, 'static>, - ) { + fn add_async_meta_callback(&mut self, meta: String, callback: AsyncCallback<'lua, 'static>) { self.async_meta_methods.push((meta, callback)) } } -impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { - fn box_method(method: M) -> Callback<'lua, 'static> +impl<'lua, T: UserData + 'static> StaticUserDataMethods<'lua, T> { + fn box_method(method: M) -> Callback<'lua, 'static> where + M: Fn(&'lua Lua, &T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result, { Box::new(move |lua, mut args| { if let Some(front) = args.pop_front() { @@ -264,11 +261,11 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { }) } - fn box_method_mut(method: M) -> Callback<'lua, 'static> + fn box_method_mut(method: M) -> Callback<'lua, 'static> where + M: FnMut(&'lua Lua, &mut T, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result, { let method = RefCell::new(method); Box::new(move |lua, mut args| { @@ -334,13 +331,13 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { } #[cfg(feature = "async")] - fn box_async_method(method: M) -> AsyncCallback<'lua, 'static> + fn box_async_method(method: M) -> AsyncCallback<'lua, 'static> where T: Clone, + M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + MR: Future> + 'lua, R: IntoLuaMulti<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR, - MR: 'lua + Future>, { Box::new(move |lua, mut args| { let fut_res = || { @@ -405,20 +402,20 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { }) } - fn box_function(function: F) -> Callback<'lua, 'static> + fn box_function(function: F) -> Callback<'lua, 'static> where + F: Fn(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result, { Box::new(move |lua, args| function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua)) } - fn box_function_mut(function: F) -> Callback<'lua, 'static> + fn box_function_mut(function: F) -> Callback<'lua, 'static> where + F: FnMut(&'lua Lua, A) -> Result + MaybeSend + 'static, A: FromLuaMulti<'lua>, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result, { let function = RefCell::new(function); Box::new(move |lua, args| { @@ -430,12 +427,12 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { } #[cfg(feature = "async")] - fn box_async_function(function: F) -> AsyncCallback<'lua, 'static> + fn box_async_function(function: F) -> AsyncCallback<'lua, 'static> where + F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static, A: FromLuaMulti<'lua>, + FR: Future> + 'lua, R: IntoLuaMulti<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR, - FR: 'lua + Future>, { Box::new(move |lua, args| { let args = match A::from_lua_multi(args, lua) { @@ -449,18 +446,18 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> { } } -pub(crate) struct StaticUserDataFields<'lua, T: 'static + UserData> { +pub(crate) struct StaticUserDataFields<'lua, T: UserData + 'static> { pub(crate) field_getters: Vec<(String, Callback<'lua, 'static>)>, pub(crate) field_setters: Vec<(String, Callback<'lua, 'static>)>, #[allow(clippy::type_complexity)] pub(crate) meta_fields: Vec<( - MetaMethod, + String, Box Result> + 'static>, )>, _type: PhantomData, } -impl<'lua, T: 'static + UserData> Default for StaticUserDataFields<'lua, T> { +impl<'lua, T: UserData + 'static> Default for StaticUserDataFields<'lua, T> { fn default() -> StaticUserDataFields<'lua, T> { StaticUserDataFields { field_getters: Vec::new(), @@ -471,67 +468,61 @@ impl<'lua, T: 'static + UserData> Default for StaticUserDataFields<'lua, T> { } } -impl<'lua, T: 'static + UserData> UserDataFields<'lua, T> for StaticUserDataFields<'lua, T> { - fn add_field_method_get(&mut self, name: &str, method: M) +impl<'lua, T: UserData + 'static> UserDataFields<'lua, T> for StaticUserDataFields<'lua, T> { + fn add_field_method_get(&mut self, name: impl AsRef, method: M) where + M: Fn(&'lua Lua, &T) -> Result + MaybeSend + 'static, R: IntoLua<'lua>, - M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result, { - self.field_getters.push(( - name.into(), - StaticUserDataMethods::box_method(move |lua, data, ()| method(lua, data)), - )); + let method = StaticUserDataMethods::box_method(move |lua, data, ()| method(lua, data)); + self.field_getters.push((name.as_ref().into(), method)); } - fn add_field_method_set(&mut self, name: &str, method: M) + fn add_field_method_set(&mut self, name: impl AsRef, method: M) where + M: FnMut(&'lua Lua, &mut T, A) -> Result<()> + MaybeSend + 'static, A: FromLua<'lua>, - M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<()>, { - self.field_setters - .push((name.into(), StaticUserDataMethods::box_method_mut(method))); + let method = StaticUserDataMethods::box_method_mut(method); + self.field_setters.push((name.as_ref().into(), method)); } - fn add_field_function_get(&mut self, name: &str, function: F) + fn add_field_function_get(&mut self, name: impl AsRef, function: F) where + F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result + MaybeSend + 'static, R: IntoLua<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result, { - self.field_getters.push(( - name.into(), - StaticUserDataMethods::::box_function(function), - )); + let func = StaticUserDataMethods::::box_function(function); + self.field_getters.push((name.as_ref().into(), func)); } - fn add_field_function_set(&mut self, name: &str, mut function: F) + fn add_field_function_set(&mut self, name: impl AsRef, mut function: F) where + F: FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()> + MaybeSend + 'static, A: FromLua<'lua>, - F: 'static + MaybeSend + FnMut(&'lua Lua, AnyUserData<'lua>, A) -> Result<()>, { - self.field_setters.push(( - name.into(), - StaticUserDataMethods::::box_function_mut(move |lua, (data, val)| { - function(lua, data, val) - }), - )); + let func = StaticUserDataMethods::::box_function_mut(move |lua, (data, val)| { + function(lua, data, val) + }); + self.field_setters.push((name.as_ref().into(), func)); } - fn add_meta_field_with(&mut self, meta: impl Into, f: F) + fn add_meta_field_with(&mut self, name: impl AsRef, f: F) where + F: Fn(&'lua Lua) -> Result + MaybeSend + 'static, R: IntoLua<'lua>, - F: 'static + MaybeSend + Fn(&'lua Lua) -> Result, { - let meta = meta.into(); + let name = name.as_ref().to_string(); self.meta_fields.push(( - meta.clone(), + name.clone(), Box::new(move |lua| { let value = f(lua)?.into_lua(lua)?; - if meta == MetaMethod::Index || meta == MetaMethod::NewIndex { + if name == MetaMethod::Index || name == MetaMethod::NewIndex { match value { Value::Nil | Value::Table(_) | Value::Function(_) => {} _ => { return Err(Error::MetaMethodTypeError { - method: meta.to_string(), + method: name.to_string(), type_name: value.type_name(), message: Some("expected nil, table or function".to_string()), }) @@ -566,7 +557,7 @@ unsafe fn get_userdata_mut<'a, T>(state: *mut ffi::lua_State) -> Result { - impl UserData for $type { + impl UserData for $type { fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { let mut orig_fields = StaticUserDataFields::default(); T::add_fields(&mut orig_fields); diff --git a/tests/userdata.rs b/tests/userdata.rs index fae0bf8..f91e840 100644 --- a/tests/userdata.rs +++ b/tests/userdata.rs @@ -543,7 +543,7 @@ fn test_metatable() -> Result<()> { fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_function("my_type_name", |_, data: AnyUserData| { let metatable = data.get_metatable()?; - metatable.get::<_, String>("__type_name") + metatable.get::("__type_name") }); } } @@ -561,7 +561,7 @@ fn test_metatable() -> Result<()> { let ud: AnyUserData = globals.get("ud")?; let metatable = ud.get_metatable()?; - match metatable.get::<_, Value>("__gc") { + match metatable.get::("__gc") { Ok(_) => panic!("expected MetaMethodRestricted, got no error"), Err(Error::MetaMethodRestricted(_)) => {} Err(e) => panic!("expected MetaMethodRestricted, got {:?}", e), @@ -575,11 +575,10 @@ fn test_metatable() -> Result<()> { let mut methods = metatable .pairs() - .into_iter() .map(|kv: Result<(_, Value)>| Ok(kv?.0)) .collect::>>()?; - methods.sort_by_cached_key(|k| k.name().to_owned()); - assert_eq!(methods, vec![MetaMethod::Index, "__type_name".into()]); + methods.sort(); + assert_eq!(methods, vec!["__index", "__type_name"]); #[derive(Copy, Clone)] struct MyUserData2(i64);