@@ -10,57 +10,56 @@ fn main() -> Result<()> {
1010 // lua std library, and will specifically allow limiting Lua to a subset of "safe"
1111 // functionality.
1212
13- let lua = Lua :: new ( ) ;
13+ Lua :: new ( ) . scope ( |lua| {
14+ // You can get and set global variables. Notice that the globals table here is a permanent
15+ // reference to _G, and it is mutated behind the scenes as lua code is loaded. This API is
16+ // based heavily around internal mutation (just like lua itself).
1417
15- // You can get and set global variables. Notice that the globals table here is a permanent
16- // reference to _G, and it is mutated behind the scenes as lua code is loaded. This API is
17- // based heavily around internal mutation (just like lua itself).
18+ let globals = lua. globals ( ) ;
1819
19- let globals = lua. globals ( ) ;
20+ globals. set ( "string_var" , "hello" ) ?;
21+ globals. set ( "int_var" , 42 ) ?;
2022
21- globals. set ( "string_var" , "hello" ) ? ;
22- globals. set ( "int_var" , 42 ) ? ;
23+ assert_eq ! ( globals. get :: <_ , String > ( "string_var" ) ? , "hello" ) ;
24+ assert_eq ! ( globals. get :: <_ , i64 > ( "int_var" ) ? , 42 ) ;
2325
24- assert_eq ! ( globals . get :: <_ , String > ( "string_var" ) ? , "hello" ) ;
25- assert_eq ! ( globals . get :: <_ , i64 > ( "int_var" ) ? , 42 ) ;
26+ // You can load and evaluate lua code. The second parameter here gives the chunk a better name
27+ // when lua error messages are printed.
2628
27- // You can load and evaluate lua code. The second parameter here gives the chunk a better name
28- // when lua error messages are printed.
29-
30- lua. exec :: < _ , ( ) > (
31- r#"
29+ lua. exec :: < _ , ( ) > (
30+ r#"
3231 global = 'foo'..'bar'
3332 "# ,
34- Some ( "example code" ) ,
35- ) ?;
36- assert_eq ! ( globals. get:: <_, String >( "global" ) ?, "foobar" ) ;
33+ Some ( "example code" ) ,
34+ ) ?;
35+ assert_eq ! ( globals. get:: <_, String >( "global" ) ?, "foobar" ) ;
3736
38- assert_eq ! ( lua. eval:: <_, i32 >( "1 + 1" , None ) ?, 2 ) ;
39- assert_eq ! ( lua. eval:: <_, bool >( "false == false" , None ) ?, true ) ;
40- assert_eq ! ( lua. eval:: <_, i32 >( "return 1 + 2" , None ) ?, 3 ) ;
37+ assert_eq ! ( lua. eval:: <_, i32 >( "1 + 1" , None ) ?, 2 ) ;
38+ assert_eq ! ( lua. eval:: <_, bool >( "false == false" , None ) ?, true ) ;
39+ assert_eq ! ( lua. eval:: <_, i32 >( "return 1 + 2" , None ) ?, 3 ) ;
4140
42- // You can create and manage lua tables
41+ // You can create and manage lua tables
4342
44- let array_table = lua. create_table ( ) ?;
45- array_table. set ( 1 , "one" ) ?;
46- array_table. set ( 2 , "two" ) ?;
47- array_table. set ( 3 , "three" ) ?;
48- assert_eq ! ( array_table. len( ) ?, 3 ) ;
43+ let array_table = lua. create_table ( ) ?;
44+ array_table. set ( 1 , "one" ) ?;
45+ array_table. set ( 2 , "two" ) ?;
46+ array_table. set ( 3 , "three" ) ?;
47+ assert_eq ! ( array_table. len( ) ?, 3 ) ;
4948
50- let map_table = lua. create_table ( ) ?;
51- map_table. set ( "one" , 1 ) ?;
52- map_table. set ( "two" , 2 ) ?;
53- map_table. set ( "three" , 3 ) ?;
54- let v: i64 = map_table. get ( "two" ) ?;
55- assert_eq ! ( v, 2 ) ;
49+ let map_table = lua. create_table ( ) ?;
50+ map_table. set ( "one" , 1 ) ?;
51+ map_table. set ( "two" , 2 ) ?;
52+ map_table. set ( "three" , 3 ) ?;
53+ let v: i64 = map_table. get ( "two" ) ?;
54+ assert_eq ! ( v, 2 ) ;
5655
57- // You can pass values like `Table` back into Lua
56+ // You can pass values like `Table` back into Lua
5857
59- globals. set ( "array_table" , array_table) ?;
60- globals. set ( "map_table" , map_table) ?;
58+ globals. set ( "array_table" , array_table) ?;
59+ globals. set ( "map_table" , map_table) ?;
6160
62- lua. eval :: < _ , ( ) > (
63- r#"
61+ lua. eval :: < _ , ( ) > (
62+ r#"
6463 for k, v in pairs(array_table) do
6564 print(k, v)
6665 end
@@ -69,119 +68,121 @@ fn main() -> Result<()> {
6968 print(k, v)
7069 end
7170 "# ,
72- None ,
73- ) ?;
74-
75- // You can load lua functions
76-
77- let print: Function = globals. get ( "print" ) ?;
78- print. call :: < _ , ( ) > ( "hello from rust" ) ?;
79-
80- // This API generally handles variadics using tuples. This is one way to call a function with
81- // multiple parameters:
82-
83- print. call :: < _ , ( ) > ( ( "hello" , "again" , "from" , "rust" ) ) ?;
84-
85- // But, you can also pass variadic arguments with the `Variadic` type.
86-
87- print. call :: < _ , ( ) > ( Variadic :: from_iter (
88- [ "hello" , "yet" , "again" , "from" , "rust" ] . iter ( ) . cloned ( ) ,
89- ) ) ?;
90-
91- // You can bind rust functions to lua as well. Callbacks receive the Lua state itself as their
92- // first parameter, and the arguments given to the function as the second parameter. The type
93- // of the arguments can be anything that is convertible from the parameters given by Lua, in
94- // this case, the function expects two string sequences.
95-
96- let check_equal = lua. create_function ( |_, ( list1, list2) : ( Vec < String > , Vec < String > ) | {
97- // This function just checks whether two string lists are equal, and in an inefficient way.
98- // Lua callbacks return `rlua::Result`, an Ok value is a normal return, and an Err return
99- // turns into a Lua 'error'. Again, any type that is convertible to lua may be returned.
100- Ok ( list1 == list2)
101- } ) ?;
102- globals. set ( "check_equal" , check_equal) ?;
103-
104- // You can also accept runtime variadic arguments to rust callbacks.
105-
106- let join = lua. create_function ( |_, strings : Variadic < String > | {
107- // (This is quadratic!, it's just an example!)
108- Ok ( strings. iter ( ) . fold ( "" . to_owned ( ) , |a, b| a + b) )
109- } ) ?;
110- globals. set ( "join" , join) ?;
111-
112- assert_eq ! (
113- lua. eval:: <_, bool >( r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"# , None ) ?,
114- true
115- ) ;
116- assert_eq ! (
117- lua. eval:: <_, bool >( r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"# , None ) ?,
118- false
119- ) ;
120- assert_eq ! (
121- lua. eval:: <_, String >( r#"join("a", "b", "c")"# , None ) ?,
122- "abc"
123- ) ;
124-
125- // You can create userdata with methods and metamethods defined on them.
126- // Here's a worked example that shows many of the features of this API
127- // together
128-
129- #[ derive( Copy , Clone ) ]
130- struct Vec2 ( f32 , f32 ) ;
131-
132- impl UserData for Vec2 {
133- fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
134- methods. add_method ( "magnitude" , |_, vec, ( ) | {
135- let mag_squared = vec. 0 * vec. 0 + vec. 1 * vec. 1 ;
136- Ok ( mag_squared. sqrt ( ) )
137- } ) ;
138-
139- methods. add_meta_function ( MetaMethod :: Add , |_, ( vec1, vec2) : ( Vec2 , Vec2 ) | {
140- Ok ( Vec2 ( vec1. 0 + vec2. 0 , vec1. 1 + vec2. 1 ) )
141- } ) ;
142- }
143- }
144-
145- let vec2_constructor = lua. create_function ( |_, ( x, y) : ( f32 , f32 ) | Ok ( Vec2 ( x, y) ) ) ?;
146- globals. set ( "vec2" , vec2_constructor) ?;
147-
148- assert ! (
149- ( lua. eval:: <_, f32 >( "(vec2(1, 2) + vec2(2, 2)):magnitude()" , None ) ? - 5.0 ) . abs( )
150- < f32 :: EPSILON
151- ) ;
152-
153- // Normally, Rust types passed to `Lua` must be `Send`, because `Lua` itself is `Send`, and must
154- // be `'static`, because there is no way to tell when Lua might garbage collect them. There is,
155- // however, a limited way to lift both of these restrictions. You can call `Lua::scope` to
156- // create userdata and callbacks types that only live for as long as the call to scope, but do
157- // not have to be `Send` OR `'static`.
158-
159- {
160- let mut rust_val = 0 ;
161-
162- lua. scope ( |scope| {
163- // We create a 'sketchy' lua callback that modifies the variable `rust_val`. Outside of a
164- // `Lua::scope` call, this would not be allowed because it could be unsafe.
165-
166- lua. globals ( ) . set (
167- "sketchy" ,
168- scope. create_function_mut ( |_, ( ) | {
169- rust_val = 42 ;
170- Ok ( ( ) )
171- } ) ?,
172- ) ?;
173-
174- lua. eval :: < _ , ( ) > ( "sketchy()" , None )
71+ None ,
72+ ) ?;
73+
74+ // You can load lua functions
75+
76+ let print: Function = globals. get ( "print" ) ?;
77+ print. call :: < _ , ( ) > ( "hello from rust" ) ?;
78+
79+ // This API generally handles variadics using tuples. This is one way to call a function with
80+ // multiple parameters:
81+
82+ print. call :: < _ , ( ) > ( ( "hello" , "again" , "from" , "rust" ) ) ?;
83+
84+ // But, you can also pass variadic arguments with the `Variadic` type.
85+
86+ print. call :: < _ , ( ) > ( Variadic :: from_iter (
87+ [ "hello" , "yet" , "again" , "from" , "rust" ] . iter ( ) . cloned ( ) ,
88+ ) ) ?;
89+
90+ // You can bind rust functions to lua as well. Callbacks receive the Lua state itself as their
91+ // first parameter, and the arguments given to the function as the second parameter. The type
92+ // of the arguments can be anything that is convertible from the parameters given by Lua, in
93+ // this case, the function expects two string sequences.
94+
95+ let check_equal =
96+ lua. create_function ( |_, ( list1, list2) : ( Vec < String > , Vec < String > ) | {
97+ // This function just checks whether two string lists are equal, and in an inefficient way.
98+ // Lua callbacks return `rlua::Result`, an Ok value is a normal return, and an Err return
99+ // turns into a Lua 'error'. Again, any type that is convertible to lua may be returned.
100+ Ok ( list1 == list2)
101+ } ) ?;
102+ globals. set ( "check_equal" , check_equal) ?;
103+
104+ // You can also accept runtime variadic arguments to rust callbacks.
105+
106+ let join = lua. create_function ( |_, strings : Variadic < String > | {
107+ // (This is quadratic!, it's just an example!)
108+ Ok ( strings. iter ( ) . fold ( "" . to_owned ( ) , |a, b| a + b) )
175109 } ) ?;
110+ globals. set ( "join" , join) ?;
111+
112+ assert_eq ! (
113+ lua. eval:: <_, bool >( r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"# , None ) ?,
114+ true
115+ ) ;
116+ assert_eq ! (
117+ lua. eval:: <_, bool >( r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"# , None ) ?,
118+ false
119+ ) ;
120+ assert_eq ! (
121+ lua. eval:: <_, String >( r#"join("a", "b", "c")"# , None ) ?,
122+ "abc"
123+ ) ;
124+
125+ // You can create userdata with methods and metamethods defined on them.
126+ // Here's a worked example that shows many of the features of this API
127+ // together
128+
129+ #[ derive( Copy , Clone ) ]
130+ struct Vec2 ( f32 , f32 ) ;
131+
132+ impl UserData for Vec2 {
133+ fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
134+ methods. add_method ( "magnitude" , |_, vec, ( ) | {
135+ let mag_squared = vec. 0 * vec. 0 + vec. 1 * vec. 1 ;
136+ Ok ( mag_squared. sqrt ( ) )
137+ } ) ;
138+
139+ methods. add_meta_function ( MetaMethod :: Add , |_, ( vec1, vec2) : ( Vec2 , Vec2 ) | {
140+ Ok ( Vec2 ( vec1. 0 + vec2. 0 , vec1. 1 + vec2. 1 ) )
141+ } ) ;
142+ }
143+ }
144+
145+ let vec2_constructor = lua. create_function ( |_, ( x, y) : ( f32 , f32 ) | Ok ( Vec2 ( x, y) ) ) ?;
146+ globals. set ( "vec2" , vec2_constructor) ?;
147+
148+ assert ! (
149+ ( lua. eval:: <_, f32 >( "(vec2(1, 2) + vec2(2, 2)):magnitude()" , None ) ? - 5.0 ) . abs( )
150+ < f32 :: EPSILON
151+ ) ;
152+
153+ // Normally, Rust types passed to `Lua` must be `Send`, because `Lua` itself is `Send`, and must
154+ // be `'static`, because there is no way to tell when Lua might garbage collect them. There is,
155+ // however, a limited way to lift both of these restrictions. You can call `Lua::scope` to
156+ // create userdata and callbacks types that only live for as long as the call to scope, but do
157+ // not have to be `Send` OR `'static`.
176158
177- assert_eq ! ( rust_val, 42 ) ;
178- }
159+ {
160+ let mut rust_val = 0 ;
161+
162+ lua. scope ( |lua| {
163+ // We create a 'sketchy' lua callback that modifies the variable `rust_val`. Outside of a
164+ // `Lua::scope` call, this would not be allowed because it could be unsafe.
165+
166+ lua. globals ( ) . set (
167+ "sketchy" ,
168+ lua. create_scoped_function_mut ( |_, ( ) | {
169+ rust_val = 42 ;
170+ Ok ( ( ) )
171+ } ) ?,
172+ ) ?;
173+
174+ lua. eval :: < _ , ( ) > ( "sketchy()" , None )
175+ } ) ?;
176+
177+ assert_eq ! ( rust_val, 42 ) ;
178+ }
179179
180- // We were able to run our 'sketchy' function inside the scope just fine. However, if we try to
181- // run our 'sketchy' function outside of the scope, the function we created will have been
182- // invalidated and we will generate an error. If our function wasn't invalidated, we might be
183- // able to improperly access the destroyed `rust_val` which would be unsafe.
184- assert ! ( lua. eval:: <_, ( ) >( "sketchy()" , None ) . is_err( ) ) ;
180+ // We were able to run our 'sketchy' function inside the scope just fine. However, if we try to
181+ // run our 'sketchy' function outside of the scope, the function we created will have been
182+ // invalidated and we will generate an error. If our function wasn't invalidated, we might be
183+ // able to improperly access the destroyed `rust_val` which would be unsafe.
184+ assert ! ( lua. eval:: <_, ( ) >( "sketchy()" , None ) . is_err( ) ) ;
185185
186- Ok ( ( ) )
186+ Ok ( ( ) )
187+ } )
187188}
0 commit comments