Skip to content

Commit 4018a17

Browse files
committed
Combine TableExt and AnyUserDataExt traits into ObjectLike
1 parent 5ebbc08 commit 4018a17

File tree

12 files changed

+300
-297
lines changed

12 files changed

+300
-297
lines changed

src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ mod stdlib;
9393
mod string;
9494
mod table;
9595
mod thread;
96+
mod traits;
9697
mod types;
9798
mod userdata;
9899
mod util;
@@ -112,12 +113,13 @@ pub use crate::state::{GCMode, Lua, LuaOptions};
112113
// pub use crate::scope::Scope;
113114
pub use crate::stdlib::StdLib;
114115
pub use crate::string::{BorrowedBytes, BorrowedStr, String};
115-
pub use crate::table::{Table, TableExt, TablePairs, TableSequence};
116+
pub use crate::table::{Table, TablePairs, TableSequence};
116117
pub use crate::thread::{Thread, ThreadStatus};
118+
pub use crate::traits::ObjectLike;
117119
pub use crate::types::{AppDataRef, AppDataRefMut, Integer, LightUserData, MaybeSend, Number, RegistryKey};
118120
pub use crate::userdata::{
119-
AnyUserData, AnyUserDataExt, MetaMethod, UserData, UserDataFields, UserDataMetatable, UserDataMethods,
120-
UserDataRef, UserDataRefMut, UserDataRegistry,
121+
AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMetatable, UserDataMethods, UserDataRef,
122+
UserDataRefMut, UserDataRegistry,
121123
};
122124
pub use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, MultiValue, Nil, Value};
123125

src/prelude.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
33
#[doc(no_inline)]
44
pub use crate::{
5-
AnyUserData as LuaAnyUserData, AnyUserDataExt as LuaAnyUserDataExt, Chunk as LuaChunk, Error as LuaError,
6-
ErrorContext as LuaErrorContext, ExternalError as LuaExternalError, ExternalResult as LuaExternalResult,
7-
FromLua, FromLuaMulti, Function as LuaFunction, FunctionInfo as LuaFunctionInfo, GCMode as LuaGCMode,
8-
Integer as LuaInteger, IntoLua, IntoLuaMulti, LightUserData as LuaLightUserData, Lua, LuaOptions,
9-
MetaMethod as LuaMetaMethod, MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber,
5+
AnyUserData as LuaAnyUserData, Chunk as LuaChunk, Error as LuaError, ErrorContext as LuaErrorContext,
6+
ExternalError as LuaExternalError, ExternalResult as LuaExternalResult, FromLua, FromLuaMulti,
7+
Function as LuaFunction, FunctionInfo as LuaFunctionInfo, GCMode as LuaGCMode, Integer as LuaInteger,
8+
IntoLua, IntoLuaMulti, LightUserData as LuaLightUserData, Lua, LuaOptions, MetaMethod as LuaMetaMethod,
9+
MultiValue as LuaMultiValue, Nil as LuaNil, Number as LuaNumber, ObjectLike as LuaObjectLike,
1010
RegistryKey as LuaRegistryKey, Result as LuaResult, StdLib as LuaStdLib, String as LuaString,
11-
Table as LuaTable, TableExt as LuaTableExt, TablePairs as LuaTablePairs,
12-
TableSequence as LuaTableSequence, Thread as LuaThread, ThreadStatus as LuaThreadStatus,
13-
UserData as LuaUserData, UserDataFields as LuaUserDataFields, UserDataMetatable as LuaUserDataMetatable,
14-
UserDataMethods as LuaUserDataMethods, UserDataRef as LuaUserDataRef,
15-
UserDataRefMut as LuaUserDataRefMut, UserDataRegistry as LuaUserDataRegistry, Value as LuaValue,
11+
Table as LuaTable, TablePairs as LuaTablePairs, TableSequence as LuaTableSequence, Thread as LuaThread,
12+
ThreadStatus as LuaThreadStatus, UserData as LuaUserData, UserDataFields as LuaUserDataFields,
13+
UserDataMetatable as LuaUserDataMetatable, UserDataMethods as LuaUserDataMethods,
14+
UserDataRef as LuaUserDataRef, UserDataRefMut as LuaUserDataRefMut,
15+
UserDataRegistry as LuaUserDataRegistry, Value as LuaValue,
1616
};
1717

1818
#[cfg(not(feature = "luau"))]

src/state/raw.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ impl RawLua {
489489
#[cfg(feature = "luau")]
490490
ffi::lua_resetthread(thread_state);
491491
extra.thread_pool.push(thread.0.index);
492-
thread.0.index = 0; // Prevent reference from being dropped
492+
thread.0.drop = false; // Prevent thread from being garbage collected
493493
return true;
494494
}
495495
false

src/table.rs

Lines changed: 57 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::HashSet;
22
use std::fmt;
33
use std::marker::PhantomData;
44
use std::os::raw::c_void;
5+
use std::string::String as StdString;
56

67
#[cfg(feature = "serialize")]
78
use {
@@ -12,14 +13,14 @@ use {
1213

1314
use crate::error::{Error, Result};
1415
use crate::function::Function;
15-
use crate::private::Sealed;
1616
use crate::state::{LuaGuard, RawLua};
17+
use crate::traits::ObjectLike;
1718
use crate::types::{Integer, ValueRef};
1819
use crate::util::{assert_stack, check_stack, StackGuard};
1920
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Nil, Value};
2021

2122
#[cfg(feature = "async")]
22-
use std::future::Future;
23+
use futures_util::future::{self, Either, Future};
2324

2425
/// Handle to an internal Lua table.
2526
#[derive(Clone)]
@@ -60,11 +61,15 @@ impl Table {
6061
///
6162
/// [`raw_set`]: #method.raw_set
6263
pub fn set(&self, key: impl IntoLua, value: impl IntoLua) -> Result<()> {
63-
// Fast track
64+
// Fast track (skip protected call)
6465
if !self.has_metatable() {
6566
return self.raw_set(key, value);
6667
}
6768

69+
self.set_protected(key, value)
70+
}
71+
72+
pub(crate) fn set_protected(&self, key: impl IntoLua, value: impl IntoLua) -> Result<()> {
6873
let lua = self.0.lua.lock();
6974
let state = lua.state();
7075
unsafe {
@@ -103,11 +108,15 @@ impl Table {
103108
///
104109
/// [`raw_get`]: #method.raw_get
105110
pub fn get<V: FromLua>(&self, key: impl IntoLua) -> Result<V> {
106-
// Fast track
111+
// Fast track (skip protected call)
107112
if !self.has_metatable() {
108113
return self.raw_get(key);
109114
}
110115

116+
self.get_protected(key)
117+
}
118+
119+
pub(crate) fn get_protected<V: FromLua>(&self, key: impl IntoLua) -> Result<V> {
111120
let lua = self.0.lua.lock();
112121
let state = lua.state();
113122
unsafe {
@@ -133,7 +142,7 @@ impl Table {
133142
///
134143
/// This might invoke the `__len` and `__newindex` metamethods.
135144
pub fn push(&self, value: impl IntoLua) -> Result<()> {
136-
// Fast track
145+
// Fast track (skip protected call)
137146
if !self.has_metatable() {
138147
return self.raw_push(value);
139148
}
@@ -158,7 +167,7 @@ impl Table {
158167
///
159168
/// This might invoke the `__len` and `__newindex` metamethods.
160169
pub fn pop<V: FromLua>(&self) -> Result<V> {
161-
// Fast track
170+
// Fast track (skip protected call)
162171
if !self.has_metatable() {
163172
return self.raw_pop();
164173
}
@@ -433,7 +442,7 @@ impl Table {
433442
///
434443
/// [`raw_len`]: #method.raw_len
435444
pub fn len(&self) -> Result<Integer> {
436-
// Fast track
445+
// Fast track (skip protected call)
437446
if !self.has_metatable() {
438447
return Ok(self.raw_len() as Integer);
439448
}
@@ -858,107 +867,41 @@ where
858867
}
859868
}
860869

861-
/// An extension trait for `Table`s that provides a variety of convenient functionality.
862-
pub trait TableExt: Sealed {
863-
/// Calls the table as function assuming it has `__call` metamethod.
864-
///
865-
/// The metamethod is called with the table as its first argument, followed by the passed
866-
/// arguments.
867-
fn call<R>(&self, args: impl IntoLuaMulti) -> Result<R>
868-
where
869-
R: FromLuaMulti;
870-
871-
/// Asynchronously calls the table as function assuming it has `__call` metamethod.
872-
///
873-
/// The metamethod is called with the table as its first argument, followed by the passed
874-
/// arguments.
875-
#[cfg(feature = "async")]
876-
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
877-
fn call_async<R>(&self, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
878-
where
879-
R: FromLuaMulti;
880-
881-
/// Gets the function associated to `key` from the table and executes it,
882-
/// passing the table itself along with `args` as function arguments.
883-
///
884-
/// This is a shortcut for
885-
/// `table.get::<Function>(key)?.call((table.clone(), arg1, ..., argN))`
886-
///
887-
/// This might invoke the `__index` metamethod.
888-
fn call_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
889-
where
890-
R: FromLuaMulti;
891-
892-
/// Gets the function associated to `key` from the table and executes it,
893-
/// passing `args` as function arguments.
894-
///
895-
/// This is a shortcut for
896-
/// `table.get::<Function>(key)?.call(args)`
897-
///
898-
/// This might invoke the `__index` metamethod.
899-
fn call_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
900-
where
901-
R: FromLuaMulti;
902-
903-
/// Gets the function associated to `key` from the table and asynchronously executes it,
904-
/// passing the table itself along with `args` as function arguments and returning Future.
905-
///
906-
/// Requires `feature = "async"`
907-
///
908-
/// This might invoke the `__index` metamethod.
909-
#[cfg(feature = "async")]
910-
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
911-
fn call_async_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
912-
where
913-
R: FromLuaMulti;
870+
impl ObjectLike for Table {
871+
#[inline]
872+
fn get<V: FromLua>(&self, key: impl IntoLua) -> Result<V> {
873+
self.get(key)
874+
}
914875

915-
/// Gets the function associated to `key` from the table and asynchronously executes it,
916-
/// passing `args` as function arguments and returning Future.
917-
///
918-
/// Requires `feature = "async"`
919-
///
920-
/// This might invoke the `__index` metamethod.
921-
#[cfg(feature = "async")]
922-
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
923-
fn call_async_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
924-
where
925-
R: FromLuaMulti;
926-
}
876+
#[inline]
877+
fn set(&self, key: impl IntoLua, value: impl IntoLua) -> Result<()> {
878+
self.set(key, value)
879+
}
927880

928-
impl TableExt for Table {
881+
#[inline]
929882
fn call<R>(&self, args: impl IntoLuaMulti) -> Result<R>
930883
where
931884
R: FromLuaMulti,
932885
{
933886
// Convert table to a function and call via pcall that respects the `__call` metamethod.
934-
Function(self.0.clone()).call(args)
887+
Function(self.0.copy()).call(args)
935888
}
936889

937890
#[cfg(feature = "async")]
891+
#[inline]
938892
fn call_async<R>(&self, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
939893
where
940894
R: FromLuaMulti,
941895
{
942-
let lua = self.0.lua.lock();
943-
let args = args.into_lua_multi(lua.lua());
944-
async move {
945-
let func = Function(self.0.clone());
946-
func.call_async(args?).await
947-
}
896+
Function(self.0.copy()).call_async(args)
948897
}
949898

899+
#[inline]
950900
fn call_method<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
951901
where
952902
R: FromLuaMulti,
953903
{
954-
self.get::<Function>(name)?.call((self, args))
955-
}
956-
957-
fn call_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R>
958-
where
959-
R: FromLuaMulti,
960-
{
961-
self.get::<Function>(name)?.call(args)
904+
self.call_function(name, (self, args))
962905
}
963906

964907
#[cfg(feature = "async")]
@@ -969,18 +912,37 @@ impl TableExt for Table {
969912
self.call_async_function(name, (self, args))
970913
}
971914

915+
#[inline]
916+
fn call_function<R: FromLuaMulti>(&self, name: &str, args: impl IntoLuaMulti) -> Result<R> {
917+
match self.get(name)? {
918+
Value::Function(func) => func.call(args),
919+
val => {
920+
let msg = format!("attempt to call a {} value (function '{name}')", val.type_name());
921+
Err(Error::runtime(msg))
922+
}
923+
}
924+
}
925+
972926
#[cfg(feature = "async")]
927+
#[inline]
973928
fn call_async_function<R>(&self, name: &str, args: impl IntoLuaMulti) -> impl Future<Output = Result<R>>
974929
where
975930
R: FromLuaMulti,
976931
{
977-
let lua = self.0.lua.lock();
978-
let args = args.into_lua_multi(lua.lua());
979-
async move {
980-
let func = self.get::<Function>(name)?;
981-
func.call_async(args?).await
932+
match self.get(name) {
933+
Ok(Value::Function(func)) => Either::Left(func.call_async(args)),
934+
Ok(val) => {
935+
let msg = format!("attempt to call a {} value (function '{name}')", val.type_name());
936+
Either::Right(future::ready(Err(Error::RuntimeError(msg))))
937+
}
938+
Err(err) => Either::Right(future::ready(Err(err))),
982939
}
983940
}
941+
942+
#[inline]
943+
fn to_string(&self) -> Result<StdString> {
944+
Value::Table(self.clone()).to_string()
945+
}
984946
}
985947

986948
/// A wrapped [`Table`] with customized serialization behavior.
@@ -1050,7 +1012,7 @@ impl<'a> Serialize for SerializableTable<'a> {
10501012
seq.serialize_element(&SerializableValue::new(&value, options, Some(visited)))
10511013
.map_err(|err| {
10521014
serialize_err = Some(err);
1053-
Error::SerializeError(String::new())
1015+
Error::SerializeError(StdString::new())
10541016
})
10551017
});
10561018
convert_result(res, serialize_err)?;
@@ -1075,7 +1037,7 @@ impl<'a> Serialize for SerializableTable<'a> {
10751037
)
10761038
.map_err(|err| {
10771039
serialize_err = Some(err);
1078-
Error::SerializeError(String::new())
1040+
Error::SerializeError(StdString::new())
10791041
})
10801042
};
10811043

0 commit comments

Comments
 (0)