mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Update UserDataMethods::add_async_method() functions to take &T as second argument instead of cloning T.
New functions: `UserDataMethods::add_async_method_mut()`, `UserDataMethods::add_async_meta_method_mut()`.
This commit is contained in:
+304
-196
@@ -1,6 +1,9 @@
|
||||
#![allow(clippy::await_holding_refcell_ref, clippy::await_holding_lock)]
|
||||
|
||||
use std::any::TypeId;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::c_int;
|
||||
use std::string::String as StdString;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
@@ -10,7 +13,7 @@ use crate::types::{Callback, MaybeSend};
|
||||
use crate::userdata::{
|
||||
AnyUserData, MetaMethod, UserData, UserDataCell, UserDataFields, UserDataMethods,
|
||||
};
|
||||
use crate::util::{check_stack, get_userdata, short_type_name, StackGuard};
|
||||
use crate::util::{get_userdata, short_type_name};
|
||||
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Value};
|
||||
|
||||
#[cfg(not(feature = "send"))]
|
||||
@@ -75,62 +78,54 @@ impl<'lua, T: 'static> UserDataRegistrar<'lua, T> {
|
||||
}
|
||||
|
||||
Box::new(move |lua, mut args| {
|
||||
let front = args.pop_front();
|
||||
let front = args
|
||||
.pop_front()
|
||||
.ok_or_else(|| Error::from_lua_conversion("missing argument", "userdata", None));
|
||||
let front = try_self_arg!(front);
|
||||
let call = |ud| {
|
||||
// Self was at index 1, so we pass 2 here
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args)?.into_lua_multi(lua)
|
||||
};
|
||||
|
||||
if let Some(front) = front {
|
||||
let state = lua.state();
|
||||
let userdata = try_self_arg!(AnyUserData::from_lua(front, lua));
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = try_self_arg!(lua.push_userdata_ref(&userdata.0));
|
||||
match type_id {
|
||||
Some(id) if id == TypeId::of::<T>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<T>(state));
|
||||
call(&ud)
|
||||
}
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(state));
|
||||
let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
|
||||
call(&ud)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(state));
|
||||
let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
|
||||
call(&ud)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
|
||||
call(&ud)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(state));
|
||||
let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
|
||||
call(&ud)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
|
||||
call(&ud)
|
||||
}
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let err = Error::from_lua_conversion("missing argument", "userdata", None);
|
||||
Err(Error::bad_self_argument(&name, err))
|
||||
let userdata = try_self_arg!(AnyUserData::from_lua(front, lua));
|
||||
let (ref_thread, index) = (lua.ref_thread(), userdata.0.index);
|
||||
match try_self_arg!(userdata.type_id()) {
|
||||
Some(id) if id == TypeId::of::<T>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_ref::<T>(ref_thread, index));
|
||||
call(&ud)
|
||||
},
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(ref_thread, index));
|
||||
let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
|
||||
call(&ud)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(ref_thread, index));
|
||||
let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
|
||||
call(&ud)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => unsafe {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
|
||||
call(&ud)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(ref_thread, index));
|
||||
let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
|
||||
call(&ud)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => unsafe {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
|
||||
call(&ud)
|
||||
},
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -156,158 +151,236 @@ impl<'lua, T: 'static> UserDataRegistrar<'lua, T> {
|
||||
let mut method = method
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| Error::RecursiveMutCallback)?;
|
||||
let front = args.pop_front();
|
||||
let front = args
|
||||
.pop_front()
|
||||
.ok_or_else(|| Error::from_lua_conversion("missing argument", "userdata", None));
|
||||
let front = try_self_arg!(front);
|
||||
let call = |ud| {
|
||||
// Self was at index 1, so we pass 2 here
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args)?.into_lua_multi(lua)
|
||||
};
|
||||
|
||||
if let Some(front) = front {
|
||||
let state = lua.state();
|
||||
let userdata = try_self_arg!(AnyUserData::from_lua(front, lua));
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = try_self_arg!(lua.push_userdata_ref(&userdata.0));
|
||||
match type_id {
|
||||
Some(id) if id == TypeId::of::<T>() => {
|
||||
let mut ud = try_self_arg!(get_userdata_mut::<T>(state));
|
||||
call(&mut ud)
|
||||
}
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(state));
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
|
||||
call(&mut ud)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(state));
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
|
||||
call(&mut ud)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(state);
|
||||
let ud = try_self_arg!(ud);
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
|
||||
call(&mut ud)
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(state));
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
|
||||
call(&mut ud)
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(state);
|
||||
let ud = try_self_arg!(ud);
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
|
||||
call(&mut ud)
|
||||
}
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let err = Error::from_lua_conversion("missing argument", "userdata", None);
|
||||
Err(Error::bad_self_argument(&name, err))
|
||||
let userdata = try_self_arg!(AnyUserData::from_lua(front, lua));
|
||||
let (ref_thread, index) = (lua.ref_thread(), userdata.0.index);
|
||||
match try_self_arg!(userdata.type_id()) {
|
||||
Some(id) if id == TypeId::of::<T>() => unsafe {
|
||||
let mut ud = try_self_arg!(get_userdata_mut::<T>(ref_thread, index));
|
||||
call(&mut ud)
|
||||
},
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(ref_thread, index));
|
||||
let mut ud = try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
|
||||
call(&mut ud)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(ref_thread, index));
|
||||
let mut ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
|
||||
call(&mut ud)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => unsafe {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let mut ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
|
||||
call(&mut ud)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(ref_thread, index));
|
||||
let mut ud = try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
|
||||
call(&mut ud)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => unsafe {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let mut ud = try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
|
||||
call(&mut ud)
|
||||
},
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn box_async_method<M, A, MR, R>(name: &str, method: M) -> AsyncCallback<'lua, 'static>
|
||||
fn box_async_method<'s, M, A, MR, R>(name: &str, method: M) -> AsyncCallback<'lua, 'static>
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
'lua: 's,
|
||||
T: 'static,
|
||||
M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = get_function_name::<T>(name);
|
||||
macro_rules! try_self_arg {
|
||||
($res:expr) => {
|
||||
$res.map_err(|err| Error::bad_self_argument(&name, err))?
|
||||
};
|
||||
($res:expr, $err:expr) => {
|
||||
$res.map_err(|_| Error::bad_self_argument(&name, $err))?
|
||||
};
|
||||
}
|
||||
let method = Arc::new(method);
|
||||
|
||||
Box::new(move |lua, mut args| {
|
||||
let front = args.pop_front();
|
||||
let call = |ud| {
|
||||
// Self was at index 1, so we pass 2 here
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
Ok(method(lua, ud, args))
|
||||
};
|
||||
|
||||
let fut_res = || {
|
||||
if let Some(front) = front {
|
||||
let state = lua.state();
|
||||
let userdata = AnyUserData::from_lua(front, lua)?;
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 2)?;
|
||||
|
||||
let type_id = try_self_arg!(lua.push_userdata_ref(&userdata.0));
|
||||
match type_id {
|
||||
Some(id) if id == TypeId::of::<T>() => {
|
||||
let ud = get_userdata_ref::<T>(state)?;
|
||||
call(ud.clone())
|
||||
}
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(state));
|
||||
let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
|
||||
call(ud.clone())
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(state));
|
||||
let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
|
||||
call(ud.clone())
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(state);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud =
|
||||
try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
|
||||
call(ud.clone())
|
||||
}
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => {
|
||||
let ud = try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(state));
|
||||
let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
|
||||
call(ud.clone())
|
||||
}
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(state);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud =
|
||||
try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
|
||||
call(ud.clone())
|
||||
}
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let err = Error::from_lua_conversion("missing argument", "userdata", None);
|
||||
Err(Error::bad_self_argument(&name, err))
|
||||
}
|
||||
};
|
||||
match fut_res() {
|
||||
Ok(fut) => {
|
||||
Box::pin(fut.and_then(move |ret| future::ready(ret.into_lua_multi(lua))))
|
||||
}
|
||||
Err(e) => Box::pin(future::err(e)),
|
||||
let name = name.clone();
|
||||
let method = method.clone();
|
||||
macro_rules! try_self_arg {
|
||||
($res:expr) => {
|
||||
$res.map_err(|err| Error::bad_self_argument(&name, err))?
|
||||
};
|
||||
($res:expr, $err:expr) => {
|
||||
$res.map_err(|_| Error::bad_self_argument(&name, $err))?
|
||||
};
|
||||
}
|
||||
|
||||
Box::pin(async move {
|
||||
let front = args.pop_front().ok_or_else(|| {
|
||||
Error::from_lua_conversion("missing argument", "userdata", None)
|
||||
});
|
||||
let front = try_self_arg!(front);
|
||||
let userdata: AnyUserData = try_self_arg!(AnyUserData::from_lua(front, lua));
|
||||
let (ref_thread, index) = (lua.ref_thread(), userdata.0.index);
|
||||
match try_self_arg!(userdata.type_id()) {
|
||||
Some(id) if id == TypeId::of::<T>() => unsafe {
|
||||
let ud = try_self_arg!(get_userdata_ref::<T>(ref_thread, index));
|
||||
let ud = std::mem::transmute::<&T, &T>(&ud);
|
||||
// Self was at index 1, so we pass 2 here
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => unsafe {
|
||||
let ud =
|
||||
try_self_arg!(get_userdata_ref::<Rc<RefCell<T>>>(ref_thread, index));
|
||||
let ud = try_self_arg!(ud.try_borrow(), Error::UserDataBorrowError);
|
||||
let ud = std::mem::transmute::<&T, &T>(&ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => unsafe {
|
||||
let ud =
|
||||
try_self_arg!(get_userdata_ref::<Arc<Mutex<T>>>(ref_thread, index));
|
||||
let ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowError);
|
||||
let ud = std::mem::transmute::<&T, &T>(&ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => unsafe {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud = try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowError));
|
||||
let ud = std::mem::transmute::<&T, &T>(&ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => unsafe {
|
||||
let ud =
|
||||
try_self_arg!(get_userdata_ref::<Arc<RwLock<T>>>(ref_thread, index));
|
||||
let ud = try_self_arg!(ud.try_read(), Error::UserDataBorrowError);
|
||||
let ud = std::mem::transmute::<&T, &T>(&ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => unsafe {
|
||||
let ud = get_userdata_ref::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let ud = try_self_arg!(ud.try_read().ok_or(Error::UserDataBorrowError));
|
||||
let ud = std::mem::transmute::<&T, &T>(&ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn box_async_method_mut<'s, M, A, MR, R>(name: &str, method: M) -> AsyncCallback<'lua, 'static>
|
||||
where
|
||||
'lua: 's,
|
||||
T: 'static,
|
||||
M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = get_function_name::<T>(name);
|
||||
let method = Arc::new(method);
|
||||
|
||||
Box::new(move |lua, mut args| {
|
||||
let name = name.clone();
|
||||
let method = method.clone();
|
||||
macro_rules! try_self_arg {
|
||||
($res:expr) => {
|
||||
$res.map_err(|err| Error::bad_self_argument(&name, err))?
|
||||
};
|
||||
($res:expr, $err:expr) => {
|
||||
$res.map_err(|_| Error::bad_self_argument(&name, $err))?
|
||||
};
|
||||
}
|
||||
|
||||
Box::pin(async move {
|
||||
let front = args.pop_front().ok_or_else(|| {
|
||||
Error::from_lua_conversion("missing argument", "userdata", None)
|
||||
});
|
||||
let front = try_self_arg!(front);
|
||||
let userdata: AnyUserData = try_self_arg!(AnyUserData::from_lua(front, lua));
|
||||
let (ref_thread, index) = (lua.ref_thread(), userdata.0.index);
|
||||
match try_self_arg!(userdata.type_id()) {
|
||||
Some(id) if id == TypeId::of::<T>() => unsafe {
|
||||
let mut ud = try_self_arg!(get_userdata_mut::<T>(ref_thread, index));
|
||||
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
|
||||
// Self was at index 1, so we pass 2 here
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
#[cfg(not(feature = "send"))]
|
||||
Some(id) if id == TypeId::of::<Rc<RefCell<T>>>() => unsafe {
|
||||
let ud =
|
||||
try_self_arg!(get_userdata_mut::<Rc<RefCell<T>>>(ref_thread, index));
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_borrow_mut(), Error::UserDataBorrowMutError);
|
||||
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<Mutex<T>>>() => unsafe {
|
||||
let ud =
|
||||
try_self_arg!(get_userdata_mut::<Arc<Mutex<T>>>(ref_thread, index));
|
||||
let mut ud = try_self_arg!(ud.try_lock(), Error::UserDataBorrowMutError);
|
||||
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::Mutex<T>>>() => unsafe {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::Mutex<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_lock().ok_or(Error::UserDataBorrowMutError));
|
||||
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
Some(id) if id == TypeId::of::<Arc<RwLock<T>>>() => unsafe {
|
||||
let ud =
|
||||
try_self_arg!(get_userdata_mut::<Arc<RwLock<T>>>(ref_thread, index));
|
||||
let mut ud = try_self_arg!(ud.try_write(), Error::UserDataBorrowMutError);
|
||||
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
#[cfg(feature = "parking_lot")]
|
||||
Some(id) if id == TypeId::of::<Arc<parking_lot::RwLock<T>>>() => unsafe {
|
||||
let ud = get_userdata_mut::<Arc<parking_lot::RwLock<T>>>(ref_thread, index);
|
||||
let ud = try_self_arg!(ud);
|
||||
let mut ud =
|
||||
try_self_arg!(ud.try_write().ok_or(Error::UserDataBorrowMutError));
|
||||
let ud = std::mem::transmute::<&mut T, &mut T>(&mut ud);
|
||||
let args = A::from_lua_multi_args(args, 2, Some(&name), lua)?;
|
||||
method(lua, ud, args).await?.into_lua_multi(lua)
|
||||
},
|
||||
_ => Err(Error::bad_self_argument(&name, Error::UserDataTypeMismatch)),
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -500,12 +573,13 @@ impl<'lua, T: 'static> UserDataMethods<'lua, T> for UserDataRegistrar<'lua, T> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_method<M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
fn add_async_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
'lua: 's,
|
||||
T: 'static,
|
||||
M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = name.as_ref();
|
||||
@@ -513,6 +587,21 @@ impl<'lua, T: 'static> UserDataMethods<'lua, T> for UserDataRegistrar<'lua, T> {
|
||||
.push((name.into(), Self::box_async_method(name, method)));
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
fn add_async_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
'lua: 's,
|
||||
T: 'static,
|
||||
M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = name.as_ref();
|
||||
self.async_methods
|
||||
.push((name.into(), Self::box_async_method_mut(name, method)));
|
||||
}
|
||||
|
||||
fn add_function<F, A, R>(&mut self, name: impl AsRef<str>, function: F)
|
||||
where
|
||||
F: Fn(&'lua Lua, A) -> Result<R> + MaybeSend + 'static,
|
||||
@@ -571,12 +660,13 @@ impl<'lua, T: 'static> UserDataMethods<'lua, T> for UserDataRegistrar<'lua, T> {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_method<M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
fn add_async_meta_method<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
T: Clone,
|
||||
M: Fn(&'lua Lua, T, A) -> MR + MaybeSend + 'static,
|
||||
'lua: 's,
|
||||
T: 'static,
|
||||
M: Fn(&'lua Lua, &'s T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 'lua,
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = name.as_ref();
|
||||
@@ -584,6 +674,21 @@ impl<'lua, T: 'static> UserDataMethods<'lua, T> for UserDataRegistrar<'lua, T> {
|
||||
.push((name.into(), Self::box_async_method(name, method)));
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "async", not(any(feature = "lua51", feature = "luau"))))]
|
||||
fn add_async_meta_method_mut<'s, M, A, MR, R>(&mut self, name: impl AsRef<str>, method: M)
|
||||
where
|
||||
'lua: 's,
|
||||
T: 'static,
|
||||
M: Fn(&'lua Lua, &'s mut T, A) -> MR + MaybeSend + 'static,
|
||||
A: FromLuaMulti<'lua>,
|
||||
MR: Future<Output = Result<R>> + 's,
|
||||
R: IntoLuaMulti<'lua>,
|
||||
{
|
||||
let name = name.as_ref();
|
||||
self.async_meta_methods
|
||||
.push((name.into(), Self::box_async_method_mut(name, method)));
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -632,13 +737,16 @@ impl<'lua, T: 'static> UserDataMethods<'lua, T> for UserDataRegistrar<'lua, T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_userdata_ref<'a, T>(state: *mut ffi::lua_State) -> Result<Ref<'a, T>> {
|
||||
(*get_userdata::<UserDataCell<T>>(state, -1)).try_borrow()
|
||||
unsafe fn get_userdata_ref<'a, T>(state: *mut ffi::lua_State, index: c_int) -> Result<Ref<'a, T>> {
|
||||
(*get_userdata::<UserDataCell<T>>(state, index)).try_borrow()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_userdata_mut<'a, T>(state: *mut ffi::lua_State) -> Result<RefMut<'a, T>> {
|
||||
(*get_userdata::<UserDataCell<T>>(state, -1)).try_borrow_mut()
|
||||
unsafe fn get_userdata_mut<'a, T>(
|
||||
state: *mut ffi::lua_State,
|
||||
index: c_int,
|
||||
) -> Result<RefMut<'a, T>> {
|
||||
(*get_userdata::<UserDataCell<T>>(state, index)).try_borrow_mut()
|
||||
}
|
||||
|
||||
macro_rules! lua_userdata_impl {
|
||||
|
||||
Reference in New Issue
Block a user