@@ -2,6 +2,7 @@ use std::collections::HashSet;
22use std:: fmt;
33use std:: marker:: PhantomData ;
44use std:: os:: raw:: c_void;
5+ use std:: string:: String as StdString ;
56
67#[ cfg( feature = "serialize" ) ]
78use {
@@ -12,14 +13,14 @@ use {
1213
1314use crate :: error:: { Error , Result } ;
1415use crate :: function:: Function ;
15- use crate :: private:: Sealed ;
1616use crate :: state:: { LuaGuard , RawLua } ;
17+ use crate :: traits:: ObjectLike ;
1718use crate :: types:: { Integer , ValueRef } ;
1819use crate :: util:: { assert_stack, check_stack, StackGuard } ;
1920use 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