Refactor `userdata::MetaMethod`.
Take `impl AsRef<str>` as name of metamethod (instead of `Into<MetaMethod>`) in UserDataMethods/UserDataFields. Change position of generic args in userdata.
This commit is contained in:
parent
22c6e9a7e7
commit
d67332a3ac
|
@ -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);
|
||||
|
||||
|
|
222
src/scope.rs
222
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<A, R, M>(&mut self, name: &str, method: M)
|
||||
fn add_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M>(&mut self, name: &str, mut method: M)
|
||||
fn add_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, mut method: M)
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M, MR>(&mut self, _name: &str, _method: M)
|
||||
fn add_async_method<M, A, MR, R>(&mut self, _name: impl AsRef<str>, _method: M)
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
// 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<A, R, F>(&mut self, name: &str, function: F)
|
||||
fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F>(&mut self, name: &str, mut function: F)
|
||||
fn add_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, mut function: F)
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F, FR>(&mut self, _name: &str, _function: F)
|
||||
fn add_async_function<F, A, FR, R>(&mut self, _name: impl AsRef<str>, _function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
FR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
// 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<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
fn add_meta_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M>(&mut self, meta: impl Into<MetaMethod>, mut method: M)
|
||||
fn add_meta_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, mut method: M)
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M, MR>(&mut self, _meta: impl Into<MetaMethod>, _method: M)
|
||||
fn add_async_meta_method<M, A, MR, R>(&mut self, _name: impl AsRef<str>, _method: M)
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
// 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<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
fn add_meta_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F>(&mut self, meta: impl Into<MetaMethod>, mut function: F)
|
||||
fn add_meta_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, mut function: F)
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F, FR>(&mut self, _meta: impl Into<MetaMethod>, _function: F)
|
||||
fn add_async_meta_function<F, A, FR, R>(&mut self, _name: impl AsRef<str>, _function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
FR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
// 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<dyn Fn(&'lua Lua) -> Result<Value<'lua>>>)>,
|
||||
meta_fields: Vec<(String, Box<dyn Fn(&'lua Lua) -> Result<Value<'lua>>>)>,
|
||||
}
|
||||
|
||||
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<R, M>(&mut self, name: &str, method: M)
|
||||
fn add_field_method_get<M, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T) -> Result<R> + MaybeSend + 'static,
|
||||
R: IntoLua<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result<R>,
|
||||
{
|
||||
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<A, M>(&mut self, name: &str, mut method: M)
|
||||
fn add_field_method_set<M, A>(&mut self, name: impl AsRef<str>, 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<R, F>(&mut self, name: &str, function: F)
|
||||
fn add_field_function_get<F, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R> + MaybeSend + 'static,
|
||||
R: IntoLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R>,
|
||||
{
|
||||
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<A, F>(&mut self, name: &str, mut function: F)
|
||||
fn add_field_function_set<F, A>(&mut self, name: impl AsRef<str>, 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<R, F>(&mut self, meta: impl Into<MetaMethod>, f: F)
|
||||
fn add_meta_field_with<F, R>(&mut self, name: impl AsRef<str>, f: F)
|
||||
where
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>,
|
||||
F: Fn(&'lua Lua) -> Result<R> + 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()),
|
||||
})
|
||||
|
|
277
src/userdata.rs
277
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<MetaMethod> for &str {
|
||||
fn eq(&self, other: &MetaMethod) -> bool {
|
||||
*self == other.name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for MetaMethod {}
|
||||
|
||||
impl Hash for MetaMethod {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.name().hash(state);
|
||||
impl PartialEq<MetaMethod> 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<Self> {
|
||||
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<StdString> 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<str> 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<A, R, M>(&mut self, name: &str, method: M)
|
||||
fn add_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>;
|
||||
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<A, R, M>(&mut self, name: &str, method: M)
|
||||
fn add_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
|
||||
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<A, R, M, MR>(&mut self, name: &str, method: M)
|
||||
fn add_async_method<M, A, MR, R>(&mut self, name: impl AsRef<str>, 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<Output = Result<R>>;
|
||||
MR: Future<Output = Result<R>> + '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<A, R, F>(&mut self, name: &str, function: F)
|
||||
fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>;
|
||||
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<A, R, F>(&mut self, name: &str, function: F)
|
||||
fn add_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>;
|
||||
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<A, R, F, FR>(&mut self, name: &str, function: F)
|
||||
fn add_async_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, 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<Output = Result<R>>;
|
||||
FR: Future<Output = Result<R>> + '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<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
fn add_meta_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>;
|
||||
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<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
fn add_meta_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>;
|
||||
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<A, R, M, MR>(&mut self, name: impl Into<MetaMethod>, method: M)
|
||||
fn add_async_meta_method<M, A, MR, R>(&mut self, name: impl AsRef<str>, 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<Output = Result<R>>;
|
||||
MR: Future<Output = Result<R>> + '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<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
fn add_meta_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>;
|
||||
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<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
fn add_meta_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>;
|
||||
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<A, R, F, FR>(&mut self, name: impl Into<MetaMethod>, function: F)
|
||||
fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, 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<Output = Result<R>>;
|
||||
FR: Future<Output = Result<R>> + '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<R, M>(&mut self, name: &str, method: M)
|
||||
fn add_field_method_get<M, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
R: IntoLua<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result<R>;
|
||||
M: Fn(&'lua Lua, &T) -> Result<R> + 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<A, M>(&mut self, name: &str, method: M)
|
||||
fn add_field_method_set<M, A>(&mut self, name: impl AsRef<str>, 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<R, F>(&mut self, name: &str, function: F)
|
||||
fn add_field_function_get<F, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
R: IntoLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R>;
|
||||
F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R> + 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<A, F>(&mut self, name: &str, function: F)
|
||||
fn add_field_function_set<F, A>(&mut self, name: impl AsRef<str>, 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<R, F>(&mut self, meta: impl Into<MetaMethod>, f: F)
|
||||
fn add_meta_field_with<F, R>(&mut self, name: impl AsRef<str>, f: F)
|
||||
where
|
||||
R: IntoLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>;
|
||||
F: Fn(&'lua Lua) -> Result<R> + 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<T> UserDataCell<T> {
|
|||
#[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<T> UserDataCell<T> {
|
|||
|
||||
// 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<T> UserDataWrapped<T> {
|
|||
#[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<T: 'static + UserData>(&self) -> bool {
|
||||
pub fn is<T: UserData + 'static>(&self) -> bool {
|
||||
match self.inspect(|_: &UserDataCell<T>| 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<T: 'static + UserData>(&self) -> Result<Ref<T>> {
|
||||
pub fn borrow<T: UserData + 'static>(&self) -> Result<Ref<T>> {
|
||||
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<T: 'static + UserData>(&self) -> Result<RefMut<T>> {
|
||||
pub fn borrow_mut<T: UserData + 'static>(&self) -> Result<RefMut<T>> {
|
||||
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<T: 'static + UserData>(&self) -> Result<T> {
|
||||
pub fn take<T: UserData + 'static>(&self) -> Result<T> {
|
||||
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<V>(&self, name: &str, v: V) -> Result<()>
|
||||
pub fn set_named_user_value<V>(&self, name: impl AsRef<str>, 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<V>(&self, name: &str) -> Result<V>
|
||||
pub fn get_named_user_value<V>(&self, name: impl AsRef<str>) -> Result<V>
|
||||
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<R>
|
||||
fn inspect<'a, T, F, R>(&'a self, func: F) -> Result<R>
|
||||
where
|
||||
T: 'static + UserData,
|
||||
T: UserData + 'static,
|
||||
F: FnOnce(&'a UserDataCell<T>) -> Result<R>,
|
||||
{
|
||||
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<K: Into<MetaMethod>, V: FromLua<'lua>>(&self, key: K) -> Result<V> {
|
||||
self.0.raw_get(key.into().validate()?.name())
|
||||
pub fn get<V: FromLua<'lua>>(&self, key: impl AsRef<str>) -> Result<V> {
|
||||
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<K: Into<MetaMethod>, V: IntoLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
||||
let key = key.into().validate()?;
|
||||
pub fn set<V: IntoLua<'lua>>(&self, key: impl AsRef<str>, 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<K: Into<MetaMethod>>(&self, key: K) -> Result<bool> {
|
||||
self.0.contains_key(key.into().validate()?.name())
|
||||
pub fn contains(&self, key: impl AsRef<str>) -> Result<bool> {
|
||||
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<Self::Item> {
|
||||
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)),
|
||||
|
|
|
@ -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<T>,
|
||||
}
|
||||
|
||||
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<A, R, M>(&mut self, name: &str, method: M)
|
||||
impl<'lua, T: UserData + 'static> UserDataMethods<'lua, T> for StaticUserDataMethods<'lua, T> {
|
||||
fn add_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
self.methods.push((name.into(), Self::box_method(method)));
|
||||
}
|
||||
|
||||
fn add_method_mut<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
self.methods
|
||||
.push((name.into(), Self::box_method_mut(method)));
|
||||
.push((name.as_ref().into(), Self::box_method(method)));
|
||||
}
|
||||
|
||||
fn add_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + 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<A, R, M, MR>(&mut self, name: &str, method: M)
|
||||
fn add_async_method<M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
self.async_methods
|
||||
.push((name.into(), Self::box_async_method(method)));
|
||||
.push((name.as_ref().into(), Self::box_async_method(method)));
|
||||
}
|
||||
|
||||
fn add_function<A, R, F>(&mut self, name: &str, function: F)
|
||||
fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.methods
|
||||
.push((name.into(), Self::box_function(function)));
|
||||
.push((name.as_ref().into(), Self::box_function(function)));
|
||||
}
|
||||
|
||||
fn add_function_mut<A, R, F>(&mut self, name: &str, function: F)
|
||||
fn add_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F, FR>(&mut self, name: &str, function: F)
|
||||
fn add_async_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
FR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
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<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
fn add_meta_method<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
self.meta_methods
|
||||
.push((meta.into(), Self::box_method(method)));
|
||||
.push((name.as_ref().into(), Self::box_method(method)));
|
||||
}
|
||||
|
||||
fn add_meta_method_mut<A, R, M>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
fn add_meta_method_mut<M, A, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M, MR>(&mut self, meta: impl Into<MetaMethod>, method: M)
|
||||
fn add_async_meta_method<M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
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<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
fn add_meta_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.meta_methods
|
||||
.push((meta.into(), Self::box_function(function)));
|
||||
.push((name.as_ref().into(), Self::box_function(function)));
|
||||
}
|
||||
|
||||
fn add_meta_function_mut<A, R, F>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
fn add_meta_function_mut<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F, FR>(&mut self, meta: impl Into<MetaMethod>, function: F)
|
||||
fn add_async_meta_function<F, A, FR, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
FR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
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<A, R, M>(method: M) -> Callback<'lua, 'static>
|
||||
impl<'lua, T: UserData + 'static> StaticUserDataMethods<'lua, T> {
|
||||
fn box_method<M, A, R>(method: M) -> Callback<'lua, 'static>
|
||||
where
|
||||
M: Fn(&'lua Lua, &T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M>(method: M) -> Callback<'lua, 'static>
|
||||
fn box_method_mut<M, A, R>(method: M) -> Callback<'lua, 'static>
|
||||
where
|
||||
M: FnMut(&'lua Lua, &mut T, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + FnMut(&'lua Lua, &mut T, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, M, MR>(method: M) -> AsyncCallback<'lua, 'static>
|
||||
fn box_async_method<M, A, MR, R>(method: M) -> AsyncCallback<'lua, 'static>
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, T, A) -> MR,
|
||||
MR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
Box::new(move |lua, mut args| {
|
||||
let fut_res = || {
|
||||
|
@ -405,20 +402,20 @@ impl<'lua, T: 'static + UserData> StaticUserDataMethods<'lua, T> {
|
|||
})
|
||||
}
|
||||
|
||||
fn box_function<A, R, F>(function: F) -> Callback<'lua, 'static>
|
||||
fn box_function<F, A, R>(function: F) -> Callback<'lua, 'static>
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
Box::new(move |lua, args| function(lua, A::from_lua_multi(args, lua)?)?.into_lua_multi(lua))
|
||||
}
|
||||
|
||||
fn box_function_mut<A, R, F>(function: F) -> Callback<'lua, 'static>
|
||||
fn box_function_mut<F, A, R>(function: F) -> Callback<'lua, 'static>
|
||||
where
|
||||
F: FnMut(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
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<A, R, F, FR>(function: F) -> AsyncCallback<'lua, 'static>
|
||||
fn box_async_function<F, A, FR, R>(function: F) -> AsyncCallback<'lua, 'static>
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> FR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
FR: Future<Output = Result<R>> + 'lua,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, A) -> FR,
|
||||
FR: 'lua + Future<Output = Result<R>>,
|
||||
{
|
||||
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<dyn Fn(&'lua Lua) -> Result<Value<'lua>> + 'static>,
|
||||
)>,
|
||||
_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
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<R, M>(&mut self, name: &str, method: M)
|
||||
impl<'lua, T: UserData + 'static> UserDataFields<'lua, T> for StaticUserDataFields<'lua, T> {
|
||||
fn add_field_method_get<M, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
M: Fn(&'lua Lua, &T) -> Result<R> + MaybeSend + 'static,
|
||||
R: IntoLua<'lua>,
|
||||
M: 'static + MaybeSend + Fn(&'lua Lua, &T) -> Result<R>,
|
||||
{
|
||||
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<A, M>(&mut self, name: &str, method: M)
|
||||
fn add_field_method_set<M, A>(&mut self, name: impl AsRef<str>, 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<R, F>(&mut self, name: &str, function: F)
|
||||
fn add_field_function_get<F, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R> + MaybeSend + 'static,
|
||||
R: IntoLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua, AnyUserData<'lua>) -> Result<R>,
|
||||
{
|
||||
self.field_getters.push((
|
||||
name.into(),
|
||||
StaticUserDataMethods::<T>::box_function(function),
|
||||
));
|
||||
let func = StaticUserDataMethods::<T>::box_function(function);
|
||||
self.field_getters.push((name.as_ref().into(), func));
|
||||
}
|
||||
|
||||
fn add_field_function_set<A, F>(&mut self, name: &str, mut function: F)
|
||||
fn add_field_function_set<F, A>(&mut self, name: impl AsRef<str>, 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::<T>::box_function_mut(move |lua, (data, val)| {
|
||||
function(lua, data, val)
|
||||
}),
|
||||
));
|
||||
let func = StaticUserDataMethods::<T>::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<R, F>(&mut self, meta: impl Into<MetaMethod>, f: F)
|
||||
fn add_meta_field_with<F, R>(&mut self, name: impl AsRef<str>, f: F)
|
||||
where
|
||||
F: Fn(&'lua Lua) -> Result<R> + MaybeSend + 'static,
|
||||
R: IntoLua<'lua>,
|
||||
F: 'static + MaybeSend + Fn(&'lua Lua) -> Result<R>,
|
||||
{
|
||||
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<RefMut<'
|
|||
|
||||
macro_rules! lua_userdata_impl {
|
||||
($type:ty) => {
|
||||
impl<T: 'static + UserData> UserData for $type {
|
||||
impl<T: UserData + 'static> 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);
|
||||
|
|
|
@ -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::<String>("__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::<Value>("__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::<Result<Vec<_>>>()?;
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue