@@ -2,6 +2,7 @@ use std::collections::HashSet;
2
2
use std:: fmt;
3
3
use std:: marker:: PhantomData ;
4
4
use std:: os:: raw:: c_void;
5
+ use std:: string:: String as StdString ;
5
6
6
7
#[ cfg( feature = "serialize" ) ]
7
8
use {
@@ -12,14 +13,14 @@ use {
12
13
13
14
use crate :: error:: { Error , Result } ;
14
15
use crate :: function:: Function ;
15
- use crate :: private:: Sealed ;
16
16
use crate :: state:: { LuaGuard , RawLua } ;
17
+ use crate :: traits:: ObjectLike ;
17
18
use crate :: types:: { Integer , ValueRef } ;
18
19
use crate :: util:: { assert_stack, check_stack, StackGuard } ;
19
20
use crate :: value:: { FromLua , FromLuaMulti , IntoLua , IntoLuaMulti , Nil , Value } ;
20
21
21
22
#[ cfg( feature = "async" ) ]
22
- use std :: future:: Future ;
23
+ use futures_util :: future:: { self , Either , Future } ;
23
24
24
25
/// Handle to an internal Lua table.
25
26
#[ derive( Clone ) ]
@@ -60,11 +61,15 @@ impl Table {
60
61
///
61
62
/// [`raw_set`]: #method.raw_set
62
63
pub fn set ( & self , key : impl IntoLua , value : impl IntoLua ) -> Result < ( ) > {
63
- // Fast track
64
+ // Fast track (skip protected call)
64
65
if !self . has_metatable ( ) {
65
66
return self . raw_set ( key, value) ;
66
67
}
67
68
69
+ self . set_protected ( key, value)
70
+ }
71
+
72
+ pub ( crate ) fn set_protected ( & self , key : impl IntoLua , value : impl IntoLua ) -> Result < ( ) > {
68
73
let lua = self . 0 . lua . lock ( ) ;
69
74
let state = lua. state ( ) ;
70
75
unsafe {
@@ -103,11 +108,15 @@ impl Table {
103
108
///
104
109
/// [`raw_get`]: #method.raw_get
105
110
pub fn get < V : FromLua > ( & self , key : impl IntoLua ) -> Result < V > {
106
- // Fast track
111
+ // Fast track (skip protected call)
107
112
if !self . has_metatable ( ) {
108
113
return self . raw_get ( key) ;
109
114
}
110
115
116
+ self . get_protected ( key)
117
+ }
118
+
119
+ pub ( crate ) fn get_protected < V : FromLua > ( & self , key : impl IntoLua ) -> Result < V > {
111
120
let lua = self . 0 . lua . lock ( ) ;
112
121
let state = lua. state ( ) ;
113
122
unsafe {
@@ -133,7 +142,7 @@ impl Table {
133
142
///
134
143
/// This might invoke the `__len` and `__newindex` metamethods.
135
144
pub fn push ( & self , value : impl IntoLua ) -> Result < ( ) > {
136
- // Fast track
145
+ // Fast track (skip protected call)
137
146
if !self . has_metatable ( ) {
138
147
return self . raw_push ( value) ;
139
148
}
@@ -158,7 +167,7 @@ impl Table {
158
167
///
159
168
/// This might invoke the `__len` and `__newindex` metamethods.
160
169
pub fn pop < V : FromLua > ( & self ) -> Result < V > {
161
- // Fast track
170
+ // Fast track (skip protected call)
162
171
if !self . has_metatable ( ) {
163
172
return self . raw_pop ( ) ;
164
173
}
@@ -433,7 +442,7 @@ impl Table {
433
442
///
434
443
/// [`raw_len`]: #method.raw_len
435
444
pub fn len ( & self ) -> Result < Integer > {
436
- // Fast track
445
+ // Fast track (skip protected call)
437
446
if !self . has_metatable ( ) {
438
447
return Ok ( self . raw_len ( ) as Integer ) ;
439
448
}
@@ -858,107 +867,41 @@ where
858
867
}
859
868
}
860
869
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
+ }
914
875
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
+ }
927
880
928
- impl TableExt for Table {
881
+ # [ inline ]
929
882
fn call < R > ( & self , args : impl IntoLuaMulti ) -> Result < R >
930
883
where
931
884
R : FromLuaMulti ,
932
885
{
933
886
// 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)
935
888
}
936
889
937
890
#[ cfg( feature = "async" ) ]
891
+ #[ inline]
938
892
fn call_async < R > ( & self , args : impl IntoLuaMulti ) -> impl Future < Output = Result < R > >
939
893
where
940
894
R : FromLuaMulti ,
941
895
{
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)
948
897
}
949
898
899
+ #[ inline]
950
900
fn call_method < R > ( & self , name : & str , args : impl IntoLuaMulti ) -> Result < R >
951
901
where
952
902
R : FromLuaMulti ,
953
903
{
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) )
962
905
}
963
906
964
907
#[ cfg( feature = "async" ) ]
@@ -969,18 +912,37 @@ impl TableExt for Table {
969
912
self . call_async_function ( name, ( self , args) )
970
913
}
971
914
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
+
972
926
#[ cfg( feature = "async" ) ]
927
+ #[ inline]
973
928
fn call_async_function < R > ( & self , name : & str , args : impl IntoLuaMulti ) -> impl Future < Output = Result < R > >
974
929
where
975
930
R : FromLuaMulti ,
976
931
{
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) ) ) ,
982
939
}
983
940
}
941
+
942
+ #[ inline]
943
+ fn to_string ( & self ) -> Result < StdString > {
944
+ Value :: Table ( self . clone ( ) ) . to_string ( )
945
+ }
984
946
}
985
947
986
948
/// A wrapped [`Table`] with customized serialization behavior.
@@ -1050,7 +1012,7 @@ impl<'a> Serialize for SerializableTable<'a> {
1050
1012
seq. serialize_element ( & SerializableValue :: new ( & value, options, Some ( visited) ) )
1051
1013
. map_err ( |err| {
1052
1014
serialize_err = Some ( err) ;
1053
- Error :: SerializeError ( String :: new ( ) )
1015
+ Error :: SerializeError ( StdString :: new ( ) )
1054
1016
} )
1055
1017
} ) ;
1056
1018
convert_result ( res, serialize_err) ?;
@@ -1075,7 +1037,7 @@ impl<'a> Serialize for SerializableTable<'a> {
1075
1037
)
1076
1038
. map_err ( |err| {
1077
1039
serialize_err = Some ( err) ;
1078
- Error :: SerializeError ( String :: new ( ) )
1040
+ Error :: SerializeError ( StdString :: new ( ) )
1079
1041
} )
1080
1042
} ;
1081
1043
0 commit comments