diff options
author | kyren <kerriganw@gmail.com> | 2018-10-01 06:00:21 -0400 |
---|---|---|
committer | kyren <kerriganw@gmail.com> | 2018-10-01 06:00:21 -0400 |
commit | 65d8ad2f8680169bb744929c526bf68896cc0a4a (patch) | |
tree | d827b786e6de3908c17798721f9de827b31c3a91 | |
parent | 8538874dd382019c482de02a75ed0a02772db2fb (diff) | |
download | mlua-65d8ad2f8680169bb744929c526bf68896cc0a4a.zip |
Allow non-utf8 Lua source in load / exec / eval
-rw-r--r-- | examples/guided_tour.rs | 25 | ||||
-rw-r--r-- | examples/repl.rs | 2 | ||||
-rw-r--r-- | src/lua.rs | 35 | ||||
-rw-r--r-- | src/multi.rs | 2 | ||||
-rw-r--r-- | src/table.rs | 2 | ||||
-rw-r--r-- | src/userdata.rs | 4 | ||||
-rw-r--r-- | tests/function.rs | 6 | ||||
-rw-r--r-- | tests/scope.rs | 6 | ||||
-rw-r--r-- | tests/string.rs | 2 | ||||
-rw-r--r-- | tests/table.rs | 6 | ||||
-rw-r--r-- | tests/tests.rs | 70 | ||||
-rw-r--r-- | tests/thread.rs | 6 | ||||
-rw-r--r-- | tests/types.rs | 2 | ||||
-rw-r--r-- | tests/userdata.rs | 14 |
14 files changed, 99 insertions, 83 deletions
diff --git a/examples/guided_tour.rs b/examples/guided_tour.rs index 292b0c0..a963fc8 100644 --- a/examples/guided_tour.rs +++ b/examples/guided_tour.rs @@ -27,7 +27,7 @@ fn main() -> Result<()> { // You can load and evaluate lua code. The second parameter here gives the chunk a better name // when lua error messages are printed. - lua.exec::<()>( + lua.exec::<_, ()>( r#" global = 'foo'..'bar' "#, @@ -35,9 +35,9 @@ fn main() -> Result<()> { )?; 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.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); // You can create and manage lua tables @@ -59,7 +59,7 @@ fn main() -> Result<()> { globals.set("array_table", array_table)?; globals.set("map_table", map_table)?; - lua.eval::<()>( + lua.eval::<_, ()>( r#" for k, v in pairs(array_table) do print(k, v) @@ -110,14 +110,17 @@ fn main() -> Result<()> { globals.set("join", join)?; assert_eq!( - lua.eval::<bool>(r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#, None)?, + lua.eval::<_, bool>(r#"check_equal({"a", "b", "c"}, {"a", "b", "c"})"#, None)?, true ); assert_eq!( - lua.eval::<bool>(r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#, None)?, + lua.eval::<_, bool>(r#"check_equal({"a", "b", "c"}, {"d", "e", "f"})"#, None)?, false ); - assert_eq!(lua.eval::<String>(r#"join("a", "b", "c")"#, None)?, "abc"); + assert_eq!( + lua.eval::<_, String>(r#"join("a", "b", "c")"#, None)?, + "abc" + ); // 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 @@ -143,7 +146,7 @@ fn main() -> Result<()> { globals.set("vec2", vec2_constructor)?; assert!( - (lua.eval::<f32>("(vec2(1, 2) + vec2(2, 2)):magnitude()", None)? - 5.0).abs() + (lua.eval::<_, f32>("(vec2(1, 2) + vec2(2, 2)):magnitude()", None)? - 5.0).abs() < f32::EPSILON ); @@ -168,7 +171,7 @@ fn main() -> Result<()> { })?, )?; - lua.eval::<()>("sketchy()", None) + lua.eval::<_, ()>("sketchy()", None) })?; assert_eq!(rust_val, 42); @@ -178,7 +181,7 @@ fn main() -> Result<()> { // 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()); + assert!(lua.eval::<_, ()>("sketchy()", None).is_err()); Ok(()) } diff --git a/examples/repl.rs b/examples/repl.rs index 4ee9ca5..3053c4e 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -20,7 +20,7 @@ fn main() { Err(_) => return, } - match lua.eval::<MultiValue>(&line, None) { + match lua.eval::<_, MultiValue>(&line, None) { Ok(values) => { editor.add_history_entry(line); println!( @@ -77,10 +77,14 @@ impl Lua { /// results in better error traces. /// /// Equivalent to Lua's `load` function. - pub fn load(&self, source: &str, name: Option<&str>) -> Result<Function> { + pub fn load<S>(&self, source: &S, name: Option<&str>) -> Result<Function> + where + S: ?Sized + AsRef<[u8]>, + { unsafe { let _sg = StackGuard::new(self.state); assert_stack(self.state, 1); + let source = source.as_ref(); match if let Some(name) = name { let name = @@ -115,11 +119,15 @@ impl Lua { /// function with no arguments. /// /// Returns the values returned by the chunk. - pub fn exec<'lua, R: FromLuaMulti<'lua>>( + pub fn exec<'lua, S, R: FromLuaMulti<'lua>>( &'lua self, - source: &str, + source: &S, name: Option<&str>, - ) -> Result<R> { + ) -> Result<R> + where + S: ?Sized + AsRef<[u8]>, + R: FromLuaMulti<'lua>, + { self.load(source, name)?.call(()) } @@ -127,15 +135,17 @@ impl Lua { /// /// If `source` is an expression, returns the value it evaluates to. Otherwise, returns the /// values returned by the chunk (if any). - pub fn eval<'lua, R: FromLuaMulti<'lua>>( - &'lua self, - source: &str, - name: Option<&str>, - ) -> Result<R> { + pub fn eval<'lua, S, R>(&'lua self, source: &S, name: Option<&str>) -> Result<R> + where + S: ?Sized + AsRef<[u8]>, + R: FromLuaMulti<'lua>, + { // First, try interpreting the lua as an expression by adding // "return", then as a statement. This is the same thing the // actual lua repl does. - self.load(&format!("return {}", source), name) + let mut return_source = "return ".as_bytes().to_vec(); + return_source.extend(source.as_ref()); + self.load(&return_source, name) .or_else(|_| self.load(source, name))? .call(()) } @@ -143,7 +153,10 @@ impl Lua { /// Create and return an interned Lua string. Lua strings can be arbitrary [u8] data including /// embedded nulls, so in addition to `&str` and `&String`, you can also pass plain `&[u8]` /// here. - pub fn create_string<S: ?Sized + AsRef<[u8]>>(&self, s: &S) -> Result<String> { + pub fn create_string<S>(&self, s: &S) -> Result<String> + where + S: ?Sized + AsRef<[u8]>, + { unsafe { let _sg = StackGuard::new(self.state); assert_stack(self.state, 4); diff --git a/src/multi.rs b/src/multi.rs index 72b45fd..83d3052 100644 --- a/src/multi.rs +++ b/src/multi.rs @@ -71,7 +71,7 @@ impl<'lua> FromLuaMulti<'lua> for MultiValue<'lua> { /// Ok(vals.iter().sum()) /// }).unwrap(); /// lua.globals().set("add", add)?; -/// assert_eq!(lua.eval::<f64>("add(3, 2, 5)", None)?, 10.0); +/// assert_eq!(lua.eval::<_, f64>("add(3, 2, 5)", None)?, 10.0); /// # Ok(()) /// # } /// # fn main() { diff --git a/src/table.rs b/src/table.rs index a32007d..fa187a2 100644 --- a/src/table.rs +++ b/src/table.rs @@ -32,7 +32,7 @@ impl<'lua> Table<'lua> { /// /// globals.set("assertions", cfg!(debug_assertions))?; /// - /// lua.exec::<()>(r#" + /// lua.exec::<_, ()>(r#" /// if assertions == true then /// -- ... /// elseif assertions == false then diff --git a/src/userdata.rs b/src/userdata.rs index 0a22e68..99e0173 100644 --- a/src/userdata.rs +++ b/src/userdata.rs @@ -219,7 +219,7 @@ pub trait UserDataMethods<'lua, T: UserData> { /// // `MyUserData` now implements `ToLua`: /// lua.globals().set("myobject", MyUserData(123))?; /// -/// lua.exec::<()>("assert(type(myobject) == 'userdata')", None)?; +/// lua.exec::<_, ()>("assert(type(myobject) == 'userdata')", None)?; /// # Ok(()) /// # } /// # fn main() { @@ -257,7 +257,7 @@ pub trait UserDataMethods<'lua, T: UserData> { /// /// lua.globals().set("myobject", MyUserData(123))?; /// -/// lua.exec::<()>(r#" +/// lua.exec::<_, ()>(r#" /// assert(myobject:get() == 123) /// myobject:add(7) /// assert(myobject:get() == 130) diff --git a/tests/function.rs b/tests/function.rs index 3e5f922..6fa1152 100644 --- a/tests/function.rs +++ b/tests/function.rs @@ -6,7 +6,7 @@ use rlua::{Function, Lua, String}; fn test_function() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function concat(arg1, arg2) return arg1 .. arg2 @@ -23,7 +23,7 @@ fn test_function() { fn test_bind() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function concat(...) local res = "" @@ -50,7 +50,7 @@ fn test_bind() { fn test_rust_function() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function lua_function() return rust_function() diff --git a/tests/scope.rs b/tests/scope.rs index aa1fe9c..c10db38 100644 --- a/tests/scope.rs +++ b/tests/scope.rs @@ -60,7 +60,7 @@ fn scope_drop() { }); assert_eq!(Rc::strong_count(&rc), 1); - match lua.exec::<()>("test:method()", None) { + match lua.exec::<_, ()>("test:method()", None) { Err(Error::CallbackError { .. }) => {} r => panic!("improper return for destructed userdata: {:?}", r), }; @@ -162,7 +162,7 @@ fn scope_userdata_functions() { let lua = Lua::new(); let f = lua - .exec::<Function>( + .exec::<_, Function>( r#" i = 0 return function(u) @@ -197,7 +197,7 @@ fn scope_userdata_mismatch() { } let lua = Lua::new(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function okay(a, b) a.inc(a) diff --git a/tests/string.rs b/tests/string.rs index 29c7593..7e4dc0e 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -30,7 +30,7 @@ fn compare() { #[test] fn string_views() { let lua = Lua::new(); - lua.eval::<()>( + lua.eval::<_, ()>( r#" ok = "null bytes are valid utf-8, wh\0 knew?" err = "but \xff isn't :(" diff --git a/tests/table.rs b/tests/table.rs index a3c6507..41d8633 100644 --- a/tests/table.rs +++ b/tests/table.rs @@ -27,7 +27,7 @@ fn test_table() { assert_eq!(table2.get::<_, String>("foo").unwrap(), "bar"); assert_eq!(table1.get::<_, String>("baz").unwrap(), "baf"); - lua.exec::<()>( + lua.exec::<_, ()>( r#" table1 = {1, 2, 3, 4, 5} table2 = {} @@ -100,7 +100,7 @@ fn test_table() { fn test_table_scope() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" touter = { tin = {1, 2, 3} @@ -149,7 +149,7 @@ fn test_metatable() { fn test_table_error() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" table = {} setmetatable(table, { diff --git a/tests/tests.rs b/tests/tests.rs index 8be28d6..4e721c6 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -28,7 +28,7 @@ fn test_debug() { Value::Table(_) => {} val => panic!("Expected table for debug library, got {:#?}", val), } - let traceback_output = lua.eval::<String>("debug.traceback()", None).unwrap(); + let traceback_output = lua.eval::<_, String>("debug.traceback()", None).unwrap(); assert_eq!( traceback_output.to_str().unwrap().split("\n").next(), "stack traceback:".into() @@ -39,7 +39,7 @@ fn test_debug() { fn test_exec() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" res = 'foo'..'bar' "#, @@ -74,10 +74,10 @@ fn test_exec() { #[test] fn test_eval() { let lua = Lua::new(); - assert_eq!(lua.eval::<i32>("1 + 1", None).unwrap(), 2); - assert_eq!(lua.eval::<bool>("false == false", None).unwrap(), true); - assert_eq!(lua.eval::<i32>("return 1 + 2", None).unwrap(), 3); - match lua.eval::<()>("if true then", None) { + assert_eq!(lua.eval::<_, i32>("1 + 1", None).unwrap(), 2); + assert_eq!(lua.eval::<_, bool>("false == false", None).unwrap(), true); + assert_eq!(lua.eval::<_, i32>("return 1 + 2", None).unwrap(), 3); + match lua.eval::<_, ()>("if true then", None) { Err(Error::SyntaxError { incomplete_input: true, .. @@ -93,7 +93,7 @@ fn test_eval() { fn test_lua_multi() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function concat(arg1, arg2) return arg1 .. arg2 @@ -121,7 +121,7 @@ fn test_lua_multi() { fn test_coercion() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" int = 123 str = "123" @@ -158,7 +158,7 @@ fn test_error() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function no_error() end @@ -245,7 +245,7 @@ fn test_error() { assert!(return_string_error.call::<_, Error>(()).is_ok()); - match lua.eval::<()>("if youre happy and you know it syntax error", None) { + match lua.eval::<_, ()>("if youre happy and you know it syntax error", None) { Err(Error::SyntaxError { incomplete_input: false, .. @@ -253,7 +253,7 @@ fn test_error() { Err(_) => panic!("error is not LuaSyntaxError::Syntax kind"), _ => panic!("error not returned"), } - match lua.eval::<()>("function i_will_finish_what_i()", None) { + match lua.eval::<_, ()>("function i_will_finish_what_i()", None) { Err(Error::SyntaxError { incomplete_input: true, .. @@ -270,7 +270,7 @@ fn test_error() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function rust_panic() pcall(function () rust_panic_function() end) @@ -296,7 +296,7 @@ fn test_error() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function rust_panic() xpcall(function() rust_panic_function() end, function() end) @@ -337,7 +337,7 @@ fn test_result_conversions() { globals.set("err", err).unwrap(); globals.set("ok", ok).unwrap(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" local r, e = err() assert(r == nil) @@ -381,19 +381,19 @@ fn test_num_conversion() { Some(1.5) ); - assert_eq!(lua.eval::<i64>("1.0", None).unwrap(), 1); - assert_eq!(lua.eval::<f64>("1.0", None).unwrap(), 1.0); - assert_eq!(lua.eval::<String>("1.0", None).unwrap(), "1.0"); + assert_eq!(lua.eval::<_, i64>("1.0", None).unwrap(), 1); + assert_eq!(lua.eval::<_, f64>("1.0", None).unwrap(), 1.0); + assert_eq!(lua.eval::<_, String>("1.0", None).unwrap(), "1.0"); - assert_eq!(lua.eval::<i64>("1.5", None).unwrap(), 1); - assert_eq!(lua.eval::<f64>("1.5", None).unwrap(), 1.5); - assert_eq!(lua.eval::<String>("1.5", None).unwrap(), "1.5"); + assert_eq!(lua.eval::<_, i64>("1.5", None).unwrap(), 1); + assert_eq!(lua.eval::<_, f64>("1.5", None).unwrap(), 1.5); + assert_eq!(lua.eval::<_, String>("1.5", None).unwrap(), "1.5"); - assert!(lua.eval::<u64>("-1", None).is_err()); - assert_eq!(lua.eval::<i64>("-1", None).unwrap(), -1); + assert!(lua.eval::<_, u64>("-1", None).is_err()); + assert_eq!(lua.eval::<_, i64>("-1", None).unwrap(), -1); assert!(lua.unpack::<u64>(lua.pack(1u128 << 64).unwrap()).is_err()); - assert!(lua.eval::<i64>("math.huge", None).is_err()); + assert!(lua.eval::<_, i64>("math.huge", None).is_err()); assert_eq!( lua.unpack::<f64>(lua.pack(f32::MAX).unwrap()).unwrap(), @@ -414,27 +414,27 @@ fn test_pcall_xpcall() { // make sure that we handle not enough arguments - assert!(lua.exec::<()>("pcall()", None).is_err()); - assert!(lua.exec::<()>("xpcall()", None).is_err()); - assert!(lua.exec::<()>("xpcall(function() end)", None).is_err()); + assert!(lua.exec::<_, ()>("pcall()", None).is_err()); + assert!(lua.exec::<_, ()>("xpcall()", None).is_err()); + assert!(lua.exec::<_, ()>("xpcall(function() end)", None).is_err()); // Make sure that the return values from are correct on success let (r, e) = lua - .eval::<(bool, String)>("pcall(function(p) return p end, 'foo')", None) + .eval::<_, (bool, String)>("pcall(function(p) return p end, 'foo')", None) .unwrap(); assert!(r); assert_eq!(e, "foo"); let (r, e) = lua - .eval::<(bool, String)>("xpcall(function(p) return p end, print, 'foo')", None) + .eval::<_, (bool, String)>("xpcall(function(p) return p end, print, 'foo')", None) .unwrap(); assert!(r); assert_eq!(e, "foo"); // Make sure that the return values are correct on errors, and that error handling works - lua.exec::<()>( + lua.exec::<_, ()>( r#" pcall_error = nil pcall_status, pcall_error = pcall(error, "testerror") @@ -458,7 +458,7 @@ fn test_pcall_xpcall() { ); // Make sure that weird xpcall error recursion at least doesn't cause unsafety or panics. - lua.exec::<()>( + lua.exec::<_, ()>( r#" function xpcall_recursion() xpcall(error, function(err) error(err) end, "testerror") @@ -515,7 +515,7 @@ fn test_recursive_mut_callback_error() { #[test] fn test_set_metatable_nil() { let lua = Lua::new(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" a = {} setmetatable(a, nil) @@ -527,7 +527,7 @@ fn test_set_metatable_nil() { #[test] fn test_gc_error() { let lua = Lua::new(); - match lua.exec::<()>( + match lua.exec::<_, ()>( r#" val = nil table = {} @@ -602,7 +602,7 @@ fn test_drop_registry_value() { drop(r); lua.expire_registry_values(); - lua.exec::<()>(r#"collectgarbage("collect")"#, None) + lua.exec::<_, ()>(r#"collectgarbage("collect")"#, None) .unwrap(); assert_eq!(Arc::strong_count(&rc), 1); @@ -658,7 +658,7 @@ fn too_many_returns() { #[test] fn too_many_arguments() { let lua = Lua::new(); - lua.exec::<()>("function test(...) end", None).unwrap(); + lua.exec::<_, ()>("function test(...) end", None).unwrap(); let args = Variadic::from_iter(1..1000000); assert!( lua.globals() @@ -691,7 +691,7 @@ fn too_many_recursions() { fn too_many_binds() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function f(...) end diff --git a/tests/thread.rs b/tests/thread.rs index c33110d..34c0560 100644 --- a/tests/thread.rs +++ b/tests/thread.rs @@ -9,7 +9,7 @@ fn test_thread() { let lua = Lua::new(); let thread = lua .create_thread( - lua.eval::<Function>( + lua.eval::<_, Function>( r#" function (s) local sum = s @@ -37,7 +37,7 @@ fn test_thread() { let accumulate = lua .create_thread( - lua.eval::<Function>( + lua.eval::<_, Function>( r#" function (sum) while true do @@ -58,7 +58,7 @@ fn test_thread() { assert_eq!(accumulate.status(), ThreadStatus::Error); let thread = lua - .eval::<Thread>( + .eval::<_, Thread>( r#" coroutine.create(function () while true do diff --git a/tests/types.rs b/tests/types.rs index 620fce5..7c5b112 100644 --- a/tests/types.rs +++ b/tests/types.rs @@ -8,7 +8,7 @@ use rlua::{Function, LightUserData, Lua}; fn test_lightuserdata() { let lua = Lua::new(); let globals = lua.globals(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function id(a) return a diff --git a/tests/userdata.rs b/tests/userdata.rs index 54a54d4..75f3975 100644 --- a/tests/userdata.rs +++ b/tests/userdata.rs @@ -46,7 +46,7 @@ fn test_methods() { let globals = lua.globals(); let userdata = lua.create_userdata(MyUserData(42)).unwrap(); globals.set("userdata", userdata.clone()).unwrap(); - lua.exec::<()>( + lua.exec::<_, ()>( r#" function get_it() return userdata:get_value() @@ -98,20 +98,20 @@ fn test_metamethods() { globals.set("userdata1", MyUserData(7)).unwrap(); globals.set("userdata2", MyUserData(3)).unwrap(); assert_eq!( - lua.eval::<MyUserData>("userdata1 + userdata2", None) + lua.eval::<_, MyUserData>("userdata1 + userdata2", None) .unwrap() .0, 10 ); assert_eq!( - lua.eval::<MyUserData>("userdata1 - userdata2", None) + lua.eval::<_, MyUserData>("userdata1 - userdata2", None) .unwrap() .0, 4 ); - assert_eq!(lua.eval::<i64>("userdata1:get()", None).unwrap(), 7); - assert_eq!(lua.eval::<i64>("userdata2.inner", None).unwrap(), 3); - assert!(lua.eval::<()>("userdata2.nonexist_field", None).is_err()); + assert_eq!(lua.eval::<_, i64>("userdata1:get()", None).unwrap(), 7); + assert_eq!(lua.eval::<_, i64>("userdata2.inner", None).unwrap(), 3); + assert!(lua.eval::<_, ()>("userdata2.nonexist_field", None).is_err()); } #[test] @@ -136,7 +136,7 @@ fn test_gc_userdata() { } assert!( - lua.eval::<()>( + lua.eval::<_, ()>( r#" local tbl = setmetatable({ userdata = userdata |