Refactor `call_async()` functions to use static dispatch outside of traits

This commit is contained in:
Alex Orlenko 2023-06-21 12:44:24 +01:00
parent b05698d55b
commit c1168d3ec1
No known key found for this signature in database
GPG Key ID: 4C150C250863B96D
5 changed files with 87 additions and 88 deletions

View File

@ -11,9 +11,6 @@ use crate::lua::Lua;
use crate::table::Table;
use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
#[cfg(feature = "async")]
use futures_util::future::{self, LocalBoxFuture};
/// Trait for types [loadable by Lua] and convertible to a [`Chunk`]
///
/// [loadable by Lua]: https://www.lua.org/manual/5.4/manual.html#3.3.2
@ -312,8 +309,8 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// [`exec`]: #method.exec
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn exec_async(self) -> LocalBoxFuture<'lua, Result<()>> {
self.call_async(())
pub async fn exec_async(self) -> Result<()> {
self.call_async(()).await
}
/// Evaluate the chunk as either an expression or block.
@ -344,17 +341,16 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// [`eval`]: #method.eval
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn eval_async<'fut, R>(self) -> LocalBoxFuture<'fut, Result<R>>
pub async fn eval_async<R>(self) -> Result<R>
where
'lua: 'fut,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
if self.detect_mode() == ChunkMode::Binary {
self.call_async(())
self.call_async(()).await
} else if let Ok(function) = self.to_expression() {
function.call_async(())
function.call_async(()).await
} else {
self.call_async(())
self.call_async(()).await
}
}
@ -374,16 +370,12 @@ impl<'lua, 'a> Chunk<'lua, 'a> {
/// [`call`]: #method.call
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn call_async<'fut, A, R>(self, args: A) -> LocalBoxFuture<'fut, Result<R>>
pub async fn call_async<A, R>(self, args: A) -> Result<R>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
match self.into_function() {
Ok(func) => func.call_async(args),
Err(e) => Box::pin(future::err(e)),
}
self.into_function()?.call_async(args).await
}
/// Load this chunk into a regular `Function`.

View File

@ -17,7 +17,7 @@ use crate::value::{FromLuaMulti, IntoLua, IntoLuaMulti};
#[cfg(feature = "async")]
use {
crate::types::AsyncCallback,
futures_util::future::{self, Future, LocalBoxFuture, TryFutureExt},
futures_util::future::{self, Future},
};
/// Handle to an internal Lua function.
@ -77,7 +77,7 @@ pub struct FunctionInfo {
#[cfg_attr(docsrs, doc(cfg(feature = "luau")))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CoverageInfo {
pub function: Option<std::string::String>,
pub function: Option<String>,
pub line_defined: i32,
pub depth: i32,
pub hits: Vec<i32>,
@ -188,21 +188,18 @@ impl<'lua> Function<'lua> {
/// [`AsyncThread`]: crate::AsyncThread
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
pub fn call_async<A, R>(&self, args: A) -> impl Future<Output = Result<R>> + 'lua
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
let lua = self.0.lua;
match lua.create_recycled_thread(self) {
Ok(t) => {
let mut t = t.into_async(args);
t.set_recyclable(true);
Box::pin(t)
}
Err(e) => Box::pin(future::err(e)),
}
let thread_res = lua.create_recycled_thread(self).map(|th| {
let mut th = th.into_async(args);
th.set_recyclable(true);
th
});
async move { thread_res?.await }
}
/// Returns a function that, when called, calls `self`, passing `args` as the first set of
@ -544,12 +541,12 @@ impl OwnedFunction {
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
#[inline]
pub fn call_async<'lua, A, R>(&'lua self, args: A) -> LocalBoxFuture<'lua, Result<R>>
pub async fn call_async<'lua, A, R>(&'lua self, args: A) -> Result<R>
where
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'lua,
{
self.to_ref().call_async(args)
self.to_ref().call_async(args).await
}
}
@ -604,7 +601,8 @@ impl<'lua> Function<'lua> {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
Box::pin(func(lua, args).and_then(move |ret| future::ready(ret.into_lua_multi(lua))))
let fut = func(lua, args);
Box::pin(async move { fut.await?.into_lua_multi(lua) })
}))
}
}

View File

@ -58,7 +58,7 @@ use crate::{
#[cfg(feature = "async")]
use {
crate::types::{AsyncCallback, AsyncCallbackUpvalue, AsyncPollUpvalue},
futures_util::future::{self, Future, TryFutureExt},
futures_util::future::{self, Future},
futures_util::task::{noop_waker_ref, Context, Poll, Waker},
};
@ -1619,7 +1619,8 @@ impl Lua {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
Box::pin(func(lua, args).and_then(move |ret| future::ready(ret.into_lua_multi(lua))))
let fut = func(lua, args);
Box::pin(async move { fut.await?.into_lua_multi(lua) })
}))
}

View File

@ -888,11 +888,10 @@ pub trait TableExt<'lua>: Sealed {
/// The metamethod is called with the table as its first argument, followed by the passed arguments.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut;
R: FromLuaMulti<'lua> + 'lua;
/// Gets the function associated to `key` from the table and executes it,
/// passing the table itself along with `args` as function arguments.
@ -928,12 +927,11 @@ pub trait TableExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
fn call_async_method<'fut, K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async_method<K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
K: IntoLua<'lua>,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut;
R: FromLuaMulti<'lua> + 'lua;
/// Gets the function associated to `key` from the table and asynchronously executes it,
/// passing `args` as function arguments and returning Future.
@ -943,16 +941,11 @@ pub trait TableExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
fn call_async_function<'fut, K, A, R>(
&self,
key: K,
args: A,
) -> LocalBoxFuture<'fut, Result<R>>
fn call_async_function<K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
K: IntoLua<'lua>,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut;
R: FromLuaMulti<'lua> + 'lua;
}
impl<'lua> TableExt<'lua> for Table<'lua> {
@ -966,13 +959,17 @@ impl<'lua> TableExt<'lua> for Table<'lua> {
}
#[cfg(feature = "async")]
fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
Function(self.0.clone()).call_async(args)
let args = match args.into_lua_multi(self.0.lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
let func = Function(self.0.clone());
Box::pin(async move { func.call_async(args).await })
}
fn call_method<K, A, R>(&self, key: K, args: A) -> Result<R>
@ -997,12 +994,11 @@ impl<'lua> TableExt<'lua> for Table<'lua> {
}
#[cfg(feature = "async")]
fn call_async_method<'fut, K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async_method<K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
K: IntoLua<'lua>,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
let lua = self.0.lua;
let mut args = match args.into_lua_multi(lua) {
@ -1014,15 +1010,19 @@ impl<'lua> TableExt<'lua> for Table<'lua> {
}
#[cfg(feature = "async")]
fn call_async_function<'fut, K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async_function<K, A, R>(&self, key: K, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
K: IntoLua<'lua>,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
let lua = self.0.lua;
let args = match args.into_lua_multi(lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
match self.get::<_, Function>(key) {
Ok(func) => func.call_async(args),
Ok(func) => Box::pin(async move { func.call_async(args).await }),
Err(e) => Box::pin(future::err(e)),
}
}

View File

@ -27,11 +27,10 @@ pub trait AnyUserDataExt<'lua>: Sealed {
/// The metamethod is called with the userdata as its first argument, followed by the passed arguments.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut;
R: FromLuaMulti<'lua> + 'lua;
/// Calls the userdata method, assuming it has `__index` metamethod
/// and a function associated to `name`.
@ -48,15 +47,14 @@ pub trait AnyUserDataExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
fn call_async_method<'fut, A, R>(
fn call_async_method<A, R>(
&self,
name: impl AsRef<str>,
args: A,
) -> LocalBoxFuture<'fut, Result<R>>
) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut;
R: FromLuaMulti<'lua> + 'lua;
/// Gets the function associated to `key` from the table and executes it,
/// passing `args` as function arguments.
@ -78,15 +76,14 @@ pub trait AnyUserDataExt<'lua>: Sealed {
/// This might invoke the `__index` metamethod.
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
fn call_async_function<'fut, A, R>(
fn call_async_function<A, R>(
&self,
name: impl AsRef<str>,
args: A,
) -> LocalBoxFuture<'fut, Result<R>>
) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut;
R: FromLuaMulti<'lua> + 'lua;
}
impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
@ -127,18 +124,24 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
}
#[cfg(feature = "async")]
fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
fn call_async<A, R>(&self, args: A) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
let metatable = match self.get_metatable() {
Ok(metatable) => metatable,
Err(err) => return Box::pin(future::err(err)),
};
match metatable.get::<Value>(MetaMethod::Call) {
Ok(Value::Function(func)) => func.call_async((self.clone(), args)),
Ok(Value::Function(func)) => {
let mut args = match args.into_lua_multi(self.0.lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
args.push_front(Value::UserData(self.clone()));
Box::pin(async move { func.call_async(args).await })
}
Ok(_) => Box::pin(future::err(Error::RuntimeError(
"attempt to call a userdata value".to_string(),
))),
@ -155,15 +158,14 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
}
#[cfg(feature = "async")]
fn call_async_method<'fut, A, R>(
fn call_async_method<A, R>(
&self,
name: impl AsRef<str>,
args: A,
) -> LocalBoxFuture<'fut, Result<R>>
) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
self.call_async_function(name, (self.clone(), args))
}
@ -183,22 +185,28 @@ impl<'lua> AnyUserDataExt<'lua> for AnyUserData<'lua> {
}
#[cfg(feature = "async")]
fn call_async_function<'fut, A, R>(
fn call_async_function<A, R>(
&self,
name: impl AsRef<str>,
args: A,
) -> LocalBoxFuture<'fut, Result<R>>
) -> LocalBoxFuture<'lua, Result<R>>
where
'lua: 'fut,
A: IntoLuaMulti<'lua>,
R: FromLuaMulti<'lua> + 'fut,
R: FromLuaMulti<'lua> + 'lua,
{
match self.get(name.as_ref()) {
Ok(Value::Function(func)) => func.call_async(args),
Ok(val) => Box::pin(future::err(Error::RuntimeError(format!(
"attempt to call a {} value",
val.type_name()
)))),
Ok(Value::Function(func)) => {
let args = match args.into_lua_multi(self.0.lua) {
Ok(args) => args,
Err(e) => return Box::pin(future::err(e)),
};
Box::pin(async move { func.call_async(args).await })
}
Ok(val) => {
let type_name = val.type_name();
let msg = format!("attempt to call a {type_name} value");
Box::pin(future::err(Error::RuntimeError(msg)))
}
Err(err) => Box::pin(future::err(err)),
}
}