From 6874c2e004f9fa92add76f1ddb4076bf80fd90ad Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Thu, 17 Oct 2019 16:59:33 +0100 Subject: [PATCH] Fix examples and docs --- examples/guided_tour.rs | 117 ++++++++++++++++++++++------------------ examples/repl.rs | 7 +-- src/function.rs | 25 +++++---- src/lua.rs | 6 +-- src/multi.rs | 6 +-- src/string.rs | 14 ++--- src/table.rs | 24 +++++---- src/thread.rs | 13 ++--- src/userdata.rs | 16 +++--- 9 files changed, 119 insertions(+), 109 deletions(-) diff --git a/examples/guided_tour.rs b/examples/guided_tour.rs index a963fc8..c42b858 100644 --- a/examples/guided_tour.rs +++ b/examples/guided_tour.rs @@ -1,20 +1,16 @@ -extern crate rlua; - use std::f32; use std::iter::FromIterator; -use rlua::{Function, Lua, MetaMethod, Result, UserData, UserDataMethods, Variadic}; +use mlua::{Function, Lua, MetaMethod, Result, UserData, UserDataMethods, Variadic}; fn main() -> Result<()> { - // Create a Lua context with `Lua::new()`. Eventually, this will allow further control on the - // lua std library, and will specifically allow limiting Lua to a subset of "safe" - // functionality. - + // You can create a new Lua state with `Lua::new()`. This loads the default Lua std library + // *without* the debug library. let lua = Lua::new(); // You can get and set global variables. Notice that the globals table here is a permanent - // reference to _G, and it is mutated behind the scenes as lua code is loaded. This API is - // based heavily around internal mutation (just like lua itself). + // reference to _G, and it is mutated behind the scenes as Lua code is loaded. This API is + // based heavily around sharing and internal mutation (just like Lua itself). let globals = lua.globals(); @@ -24,22 +20,25 @@ fn main() -> Result<()> { assert_eq!(globals.get::<_, String>("string_var")?, "hello"); assert_eq!(globals.get::<_, i64>("int_var")?, 42); - // You can load and evaluate lua code. The second parameter here gives the chunk a better name - // when lua error messages are printed. + // You can load and evaluate Lua code. The returned type of `Lua::load` is a builder + // that allows you to change settings before running Lua code. Here, we are using it to set + // the name of the laoded chunk to "example code", which will be used when Lua error + // messages are printed. - lua.exec::<_, ()>( + lua.load( r#" global = 'foo'..'bar' "#, - Some("example code"), - )?; + ) + .set_name("example code")? + .exec()?; assert_eq!(globals.get::<_, String>("global")?, "foobar"); - assert_eq!(lua.eval::<_, i32>("1 + 1", None)?, 2); - assert_eq!(lua.eval::<_, bool>("false == false", None)?, true); - assert_eq!(lua.eval::<_, i32>("return 1 + 2", None)?, 3); + assert_eq!(lua.load("1 + 1").eval::()?, 2); + assert_eq!(lua.load("false == false").eval::()?, true); + assert_eq!(lua.load("return 1 + 2").eval::()?, 3); - // You can create and manage lua tables + // You can create and manage Lua tables let array_table = lua.create_table()?; array_table.set(1, "one")?; @@ -59,20 +58,20 @@ fn main() -> Result<()> { globals.set("array_table", array_table)?; globals.set("map_table", map_table)?; - lua.eval::<_, ()>( + lua.load( r#" - for k, v in pairs(array_table) do - print(k, v) - end + for k, v in pairs(array_table) do + print(k, v) + end - for k, v in pairs(map_table) do - print(k, v) - end + for k, v in pairs(map_table) do + print(k, v) + end "#, - None, - )?; + ) + .exec()?; - // You can load lua functions + // You can load Lua functions let print: Function = globals.get("print")?; print.call::<_, ()>("hello from rust")?; @@ -88,15 +87,15 @@ fn main() -> Result<()> { ["hello", "yet", "again", "from", "rust"].iter().cloned(), ))?; - // You can bind rust functions to lua as well. Callbacks receive the Lua state itself as their + // You can bind rust functions to Lua as well. Callbacks receive the Lua state inself as their // first parameter, and the arguments given to the function as the second parameter. The type // of the arguments can be anything that is convertible from the parameters given by Lua, in // this case, the function expects two string sequences. let check_equal = lua.create_function(|_, (list1, list2): (Vec, Vec)| { // This function just checks whether two string lists are equal, and in an inefficient way. - // Lua callbacks return `rlua::Result`, an Ok value is a normal return, and an Err return - // turns into a Lua 'error'. Again, any type that is convertible to lua may be returned. + // Lua callbacks return `mlua::Result`, an Ok value is a normal return, and an Err return + // turns into a Lua 'error'. Again, any type that is convertible to Lua may be returned. Ok(list1 == list2) })?; globals.set("check_equal", check_equal)?; @@ -110,17 +109,29 @@ fn main() -> Result<()> { globals.set("join", join)?; assert_eq!( - lua.eval::<_, bool>(r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#, None)?, + lua.load(r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#) + .eval::()?, true ); assert_eq!( - lua.eval::<_, bool>(r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#, None)?, + lua.load(r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#) + .eval::()?, false ); - assert_eq!( - lua.eval::<_, String>(r#"join("a", "b", "c")"#, None)?, - "abc" - ); + assert_eq!(lua.load(r#"join("a", "b", "c")"#).eval::()?, "abc"); + + // Callbacks receive a Lua state as their first parameter so that they can use it to + // create new Lua values, if necessary. + + let create_table = lua.create_function(|lua, ()| { + let t = lua.create_table()?; + t.set(1, 1)?; + t.set(2, 2)?; + Ok(t) + })?; + globals.set("create_table", create_table)?; + + assert_eq!(lua.load(r#"create_table()[2]"#).eval::()?, 2); // You can create userdata with methods and metamethods defined on them. // Here's a worked example that shows many of the features of this API @@ -146,22 +157,26 @@ fn main() -> Result<()> { globals.set("vec2", vec2_constructor)?; assert!( - (lua.eval::<_, f32>("(vec2(1, 2) + vec2(2, 2)):magnitude()", None)? - 5.0).abs() + (lua.load("(vec2(1, 2) + vec2(2, 2)):magnitude()") + .eval::()? + - 5.0) + .abs() < f32::EPSILON ); - // Normally, Rust types passed to `Lua` must be `Send`, because `Lua` itself is `Send`, and must - // be `'static`, because there is no way to tell when Lua might garbage collect them. There is, - // however, a limited way to lift both of these restrictions. You can call `Lua::scope` to - // create userdata and callbacks types that only live for as long as the call to scope, but do - // not have to be `Send` OR `'static`. + // Normally, Rust types passed to `Lua` must be `Send`, because `Lua` itself is `Send`, and + // must be `'static`, because there is no way to be sure of their lifetime inside the Lua + // state. There is, however, a limited way to lift both of these requirements. You can + // call `Lua::scope` to create userdata and callbacks types that only live for as long + // as the call to scope, but do not have to be `Send` OR `'static`. { let mut rust_val = 0; lua.scope(|scope| { - // We create a 'sketchy' lua callback that modifies the variable `rust_val`. Outside of a - // `Lua::scope` call, this would not be allowed because it could be unsafe. + // We create a 'sketchy' Lua callback that holds a mutable reference to the variable + // `rust_val`. Outside of a `Lua::scope` call, this would not be allowed + // because it could be unsafe. lua.globals().set( "sketchy", @@ -171,17 +186,17 @@ fn main() -> Result<()> { })?, )?; - lua.eval::<_, ()>("sketchy()", None) + lua.load("sketchy()").exec() })?; assert_eq!(rust_val, 42); } - // We were able to run our 'sketchy' function inside the scope just fine. However, if we try to - // run our 'sketchy' function outside of the scope, the function we created will have been - // invalidated and we will generate an error. If our function wasn't invalidated, we might be - // able to improperly access the destroyed `rust_val` which would be unsafe. - assert!(lua.eval::<_, ()>("sketchy()", None).is_err()); + // We were able to run our 'sketchy' function inside the scope just fine. However, if we + // try to run our 'sketchy' function outside of the scope, the function we created will have + // been invalidated and we will generate an error. If our function wasn't invalidated, we + // might be able to improperly access the freed `rust_val` which would be unsafe. + assert!(lua.load("sketchy()").exec().is_err()); Ok(()) } diff --git a/examples/repl.rs b/examples/repl.rs index 3053c4e..a5fe47a 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -1,9 +1,6 @@ //! This example shows a simple read-evaluate-print-loop (REPL). -extern crate rlua; -extern crate rustyline; - -use rlua::{Error, Lua, MultiValue}; +use mlua::{Error, Lua, MultiValue}; use rustyline::Editor; fn main() { @@ -20,7 +17,7 @@ fn main() { Err(_) => return, } - match lua.eval::<_, MultiValue>(&line, None) { + match lua.load(&line).eval::() { Ok(values) => { editor.add_history_entry(line); println!( diff --git a/src/function.rs b/src/function.rs index b0b6303..1b7e6fe 100644 --- a/src/function.rs +++ b/src/function.rs @@ -23,9 +23,9 @@ impl<'lua> Function<'lua> { /// Call Lua's built-in `tostring` function: /// /// ``` - /// # use mlua::{Lua, Function, Result}; + /// # use mlua::{Function, Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); + /// # let lua = Lua::new(); /// let globals = lua.globals(); /// /// let tostring: Function = globals.get("tostring")?; @@ -39,16 +39,15 @@ impl<'lua> Function<'lua> { /// Call a function with multiple arguments: /// /// ``` - /// # use mlua::{Lua, Function, Result}; + /// # use mlua::{Function, Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); - /// + /// # let lua = Lua::new(); /// let sum: Function = lua.load( /// r#" /// function(a, b) /// return a + b /// end - /// "#).eval()?; + /// "#).eval()?; /// /// assert_eq!(sum.call::<_, u32>((3, 4))?, 3 + 4); /// @@ -95,14 +94,14 @@ impl<'lua> Function<'lua> { /// # Examples /// /// ``` - /// # use mlua::{Lua, Function, Result}; + /// # use mlua::{Function, Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); - /// - /// let sum: Function = lua_context.load(r#" - /// function(a, b) - /// return a + b - /// end + /// # let lua = Lua::new(); + /// let sum: Function = lua.load( + /// r#" + /// function(a, b) + /// return a + b + /// end /// "#).eval()?; /// /// let bound_a = sum.bind(1)?; diff --git a/src/lua.rs b/src/lua.rs index 8896e89..71e131d 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -414,8 +414,7 @@ impl Lua { /// ``` /// # use mlua::{Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); - /// + /// # let lua = Lua::new(); /// let greet = lua.create_function(|_, name: String| { /// println!("Hello, {}!", name); /// Ok(()) @@ -430,8 +429,7 @@ impl Lua { /// ``` /// # use mlua::{Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); - /// + /// # let lua = Lua::new(); /// let print_person = lua.create_function(|_, (name, age): (String, u8)| { /// println!("{} is {} years old!", name, age); /// Ok(()) diff --git a/src/multi.rs b/src/multi.rs index 2330c90..46a673f 100644 --- a/src/multi.rs +++ b/src/multi.rs @@ -62,12 +62,12 @@ impl<'lua> FromLuaMulti<'lua> for MultiValue<'lua> { /// # Examples /// /// ``` -/// # use mlua::{Lua, Variadic, Result}; +/// # use mlua::{Lua, Result, Variadic}; /// # fn main() -> Result<()> { -/// let lua = Lua::new(); +/// # let lua = Lua::new(); /// let add = lua.create_function(|_, vals: Variadic| -> Result { /// Ok(vals.iter().sum()) -/// }).unwrap(); +/// })?; /// lua.globals().set("add", add)?; /// assert_eq!(lua.load("add(3, 2, 5)").eval::()?, 10.0); /// # Ok(()) diff --git a/src/string.rs b/src/string.rs index 7add659..cdb8827 100644 --- a/src/string.rs +++ b/src/string.rs @@ -17,15 +17,15 @@ impl<'lua> String<'lua> { /// # Examples /// /// ``` - /// # use mlua::{Lua, String, Result}; + /// # use mlua::{Lua, Result, String}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); + /// # let lua = Lua::new(); /// let globals = lua.globals(); /// /// let version: String = globals.get("_VERSION")?; - /// assert!(version.to_str().unwrap().contains("Lua")); + /// assert!(version.to_str()?.contains("Lua")); /// - /// let non_utf8: String = lua.load(r#" "test\xff" "#).eval()?; + /// let non_utf8: String = lua.load(r#" "test\255" "#).eval()?; /// assert!(non_utf8.to_str().is_err()); /// # Ok(()) /// # } @@ -46,10 +46,10 @@ impl<'lua> String<'lua> { /// # Examples /// /// ``` - /// # use mlua::{Lua, String, Result}; + /// # use mlua::{Lua, Result, String}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); - /// let non_utf8: String = lua.load(r#" "test\xff" "#).eval()?; + /// # let lua = Lua::new(); + /// let non_utf8: String = lua.load(r#" "test\255" "#).eval()?; /// assert!(non_utf8.to_str().is_err()); // oh no :( /// assert_eq!(non_utf8.as_bytes(), &b"test\xff"[..]); /// # Ok(()) diff --git a/src/table.rs b/src/table.rs index 7a5be54..0c3e143 100644 --- a/src/table.rs +++ b/src/table.rs @@ -27,12 +27,12 @@ impl<'lua> Table<'lua> { /// ``` /// # use mlua::{Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); + /// # let lua = Lua::new(); /// let globals = lua.globals(); /// /// globals.set("assertions", cfg!(debug_assertions))?; /// - /// lua.exec::<_, ()>(r#" + /// lua.load(r#" /// if assertions == true then /// -- ... /// elseif assertions == false then @@ -40,7 +40,7 @@ impl<'lua> Table<'lua> { /// else /// error("assertions neither on nor off?") /// end - /// "#, None)?; + /// "#).exec()?; /// # Ok(()) /// # } /// ``` @@ -80,7 +80,7 @@ impl<'lua> Table<'lua> { /// ``` /// # use mlua::{Lua, Result}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); + /// # let lua = Lua::new(); /// let globals = lua.globals(); /// /// let version: String = globals.get("_VERSION")?; @@ -134,19 +134,21 @@ impl<'lua> Table<'lua> { } /// Gets the function associated to `key` from the table and executes it, - /// passing the table as the first argument. + /// passing the table itself as the first argument. /// /// # Examples /// /// Execute the table method with name "concat": /// /// ``` - /// # use mlua::{Function, Lua, Result}; + /// # use mlua::{Lua, Result, Table}; /// # fn main() -> Result<()> { /// # let lua = Lua::new(); - /// # let table = lua.create_table(); - /// // Lua: table:concat("param1", "param2") - /// table.call("concat", ("param1", "param2"))?; + /// # let object = lua.create_table()?; + /// # let concat = lua.create_function(|_, (_, a, b): (Table, String, String)| Ok(a + &b))?; + /// # object.set("concat", concat)?; + /// // simiar to: object:concat("param1", "param2") + /// object.call("concat", ("param1", "param2"))?; /// # Ok(()) /// # } /// ``` @@ -294,7 +296,7 @@ impl<'lua> Table<'lua> { /// ``` /// # use mlua::{Lua, Result, Value}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); + /// # let lua = Lua::new(); /// let globals = lua.globals(); /// /// for pair in globals.pairs::() { @@ -336,7 +338,7 @@ impl<'lua> Table<'lua> { /// ``` /// # use mlua::{Lua, Result, Table}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); + /// # let lua = Lua::new(); /// let my_table: Table = lua.load(r#" /// { /// [1] = 4, diff --git a/src/thread.rs b/src/thread.rs index 52ec66a..97b0362 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -46,26 +46,27 @@ impl<'lua> Thread<'lua> { /// # Examples /// /// ``` - /// # use mlua::{Lua, Thread, Error}; + /// # use mlua::{Error, Lua, Result, Thread}; /// # fn main() -> Result<()> { - /// let lua = Lua::new(); - /// let thread: Thread = lua.eval(r#" + /// # let lua = Lua::new(); + /// let thread: Thread = lua.load(r#" /// coroutine.create(function(arg) /// assert(arg == 42) /// local yieldarg = coroutine.yield(123) /// assert(yieldarg == 43) /// return 987 /// end) - /// "#, None).unwrap(); + /// "#).eval()?; /// - /// assert_eq!(thread.resume::<_, u32>(42).unwrap(), 123); - /// assert_eq!(thread.resume::<_, u32>(43).unwrap(), 987); + /// assert_eq!(thread.resume::<_, u32>(42)?, 123); + /// assert_eq!(thread.resume::<_, u32>(43)?, 987); /// /// // The coroutine has now returned, so `resume` will fail /// match thread.resume::<_, u32>(()) { /// Err(Error::CoroutineInactive) => {}, /// unexpected => panic!("unexpected result {:?}", unexpected), /// } + /// # Ok(()) /// # } /// ``` pub fn resume(&self, args: A) -> Result diff --git a/src/userdata.rs b/src/userdata.rs index 617e0c1..bc6b62e 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -212,18 +212,17 @@ pub trait UserDataMethods<'lua, T: UserData> { /// # Examples /// /// ``` -/// # use mlua::{Lua, UserData, Result}; +/// # use mlua::{Lua, Result, UserData}; /// # fn main() -> Result<()> { +/// # let lua = Lua::new(); /// struct MyUserData(i32); /// /// impl UserData for MyUserData {} /// -/// let lua = Lua::new(); -/// /// // `MyUserData` now implements `ToLua`: /// lua.globals().set("myobject", MyUserData(123))?; /// -/// lua.exec::<_, ()>("assert(type(myobject) == 'userdata')", None)?; +/// lua.load("assert(type(myobject) == 'userdata')").exec()?; /// # Ok(()) /// # } /// ``` @@ -232,8 +231,9 @@ pub trait UserDataMethods<'lua, T: UserData> { /// [`UserDataMethods`] for more information): /// /// ``` -/// # use mlua::{Lua, MetaMethod, UserData, UserDataMethods, Result}; +/// # use mlua::{Lua, MetaMethod, Result, UserData, UserDataMethods}; /// # fn main() -> Result<()> { +/// # let lua = Lua::new(); /// struct MyUserData(i32); /// /// impl UserData for MyUserData { @@ -253,16 +253,14 @@ pub trait UserDataMethods<'lua, T: UserData> { /// } /// } /// -/// let lua = Lua::new(); -/// /// lua.globals().set("myobject", MyUserData(123))?; /// -/// lua.exec::<_, ()>(r#" +/// lua.load(r#" /// assert(myobject:get() == 123) /// myobject:add(7) /// assert(myobject:get() == 130) /// assert(myobject + 10 == 140) -/// "#, None)?; +/// "#).exec()?; /// # Ok(()) /// # } /// ```