summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/table.rs37
-rw-r--r--tests/table.rs17
2 files changed, 52 insertions, 2 deletions
diff --git a/src/table.rs b/src/table.rs
index 4794d97..879a730 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -502,6 +502,24 @@ impl<'lua> AsRef<Table<'lua>> for Table<'lua> {
/// An extension trait for `Table`s that provides a variety of convenient functionality.
pub trait TableExt<'lua> {
+ /// Calls the table as function assuming it has `__call` metamethod.
+ ///
+ /// The metamethod is called with the table as its first argument, followed by the passed arguments.
+ fn call<A, R>(&self, args: A) -> Result<R>
+ where
+ A: ToLuaMulti<'lua>,
+ R: FromLuaMulti<'lua>;
+
+ /// Asynchronously calls the table as function assuming it has `__call` metamethod.
+ ///
+ /// The metamethod is called with the table as its first argument, followed by the passed arguments.
+ #[cfg(feature = "async")]
+ fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
+ where
+ 'lua: 'fut,
+ A: ToLuaMulti<'lua>,
+ R: FromLuaMulti<'lua> + 'fut;
+
/// Gets the function associated to `key` from the table and executes it,
/// passing the table itself along with `args` as function arguments.
///
@@ -564,6 +582,25 @@ pub trait TableExt<'lua> {
}
impl<'lua> TableExt<'lua> for Table<'lua> {
+ fn call<A, R>(&self, args: A) -> Result<R>
+ where
+ A: ToLuaMulti<'lua>,
+ R: FromLuaMulti<'lua>,
+ {
+ // Convert table to a function and call via pcall that respects the `__call` metamethod.
+ Function(self.0.clone()).call(args)
+ }
+
+ #[cfg(feature = "async")]
+ fn call_async<'fut, A, R>(&self, args: A) -> LocalBoxFuture<'fut, Result<R>>
+ where
+ 'lua: 'fut,
+ A: ToLuaMulti<'lua>,
+ R: FromLuaMulti<'lua> + 'fut,
+ {
+ Function(self.0.clone()).call_async(args)
+ }
+
fn call_method<K, A, R>(&self, key: K, args: A) -> Result<R>
where
K: ToLua<'lua>,
diff --git a/tests/table.rs b/tests/table.rs
index b22696d..3ee0797 100644
--- a/tests/table.rs
+++ b/tests/table.rs
@@ -1,4 +1,4 @@
-use mlua::{Lua, Nil, Result, Table, TableExt, Value};
+use mlua::{Error, Lua, Nil, Result, Table, TableExt, Value};
#[test]
fn test_set_get() -> Result<()> {
@@ -266,7 +266,12 @@ fn test_table_call() -> Result<()> {
lua.load(
r#"
- table = {a = 1}
+ table = {a = 1, b = 2}
+ setmetatable(table, {
+ __call = function(t, key)
+ return "call_"..t[key]
+ end
+ })
function table.func(key)
return "func_"..key
@@ -281,11 +286,19 @@ fn test_table_call() -> Result<()> {
let table: Table = lua.globals().get("table")?;
+ assert_eq!(table.call::<_, String>("b")?, "call_2");
assert_eq!(table.call_function::<_, _, String>("func", "a")?, "func_a");
assert_eq!(
table.call_method::<_, _, String>("method", "a")?,
"method_1"
);
+ // Test calling non-callable table
+ let table2 = lua.create_table()?;
+ assert!(matches!(
+ table2.call::<_, ()>(()),
+ Err(Error::RuntimeError(_))
+ ));
+
Ok(())
}