diff --git a/Cargo.toml b/Cargo.toml index 2a99b7d..2342454 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rlua" -version = "0.1.0" +version = "0.2.0" authors = ["kyren "] repository = "https://github.com/chucklefish/rlua" description = "High level bindings to Lua 5.3" @@ -9,7 +9,8 @@ keywords = ["lua"] license = "MIT" [build-dependencies] -gcc = "*" +gcc = "0.3" [dependencies] -error-chain = "*" +hlist-macro = "0.1" +error-chain = "0.10" diff --git a/README.md b/README.md index 3ece035..9fca154 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,12 @@ in rustc. For example: See [this reddit discussion](http://www.reddit.com/r/rust/comments/5yujt6/) for details of the current lifetime problem with callback wrapping. +## API Stability or lack thereof + +This library is very much Work In Progress, so there may be a lot of API churn. +I will try to follow a pre-1.0 semver (if such a thing exists), but that means +there will just be a large number of API bumps. + ## Safety My *goal* is complete safety, it should not be possible to cause undefined @@ -85,4 +91,5 @@ The library currently attempts to handle each of these situations, but there are so many ways to cause unsafety with Lua that it just needs more testing. ## Examples + Please look at the examples [here](examples/examples.rs). diff --git a/examples/examples.rs b/examples/examples.rs index 99c452b..a4dd8bd 100644 --- a/examples/examples.rs +++ b/examples/examples.rs @@ -1,4 +1,5 @@ #[macro_use] +extern crate hlist_macro; extern crate rlua; use rlua::*; @@ -70,7 +71,7 @@ fn examples() -> LuaResult<()> { // is one way to call a function with multiple parameters: print - .call::<_, ()>(lua_multi!["hello", "again", "from", "rust"])?; + .call::<_, ()>(hlist!["hello", "again", "from", "rust"])?; // You can bind rust functions to lua as well @@ -80,7 +81,7 @@ fn examples() -> LuaResult<()> { // parts. Due to lifetime type signature limitations, this cannot be done automatically from the // function signature, but this will be fixed with ATCs. Notice the use of the hlist // macros again. - let lua_multi_pat![list1, list2] = lua.unpack::, Vec]>(args)?; + let hlist_pat![list1, list2] = lua.unpack::, Vec]>(args)?; // This function just checks whether two string lists are equal, and in an inefficient way. // Results are returned with lua.pack, which takes any number of values and turns them back @@ -119,14 +120,14 @@ fn examples() -> LuaResult<()> { }); methods.add_meta_function(LuaMetaMethod::Add, |lua, params| { - let lua_multi_pat![vec1, vec2] = lua.unpack::(params)?; + let hlist_pat![vec1, vec2] = lua.unpack::(params)?; lua.pack(Vec2(vec1.0 + vec2.0, vec1.1 + vec2.1)) }); } } let vec2_constructor = lua.create_function(|lua, args| { - let lua_multi_pat![x, y] = lua.unpack::(args)?; + let hlist_pat![x, y] = lua.unpack::(args)?; lua.pack(Vec2(x, y)) })?; lua.set("vec2", vec2_constructor)?; diff --git a/src/lib.rs b/src/lib.rs index be41a52..834e557 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,14 @@ +#[cfg(test)] +#[macro_use] +extern crate hlist_macro; + +#[cfg(not(test))] +extern crate hlist_macro; + #[macro_use] extern crate error_chain; - pub mod ffi; -#[macro_use] -mod macros; mod util; mod error; mod lua; diff --git a/src/multi.rs b/src/multi.rs index 0ce2d04..d68ce8d 100644 --- a/src/multi.rs +++ b/src/multi.rs @@ -1,12 +1,8 @@ +use hlist_macro::{HNil, HCons}; + use error::*; use lua::*; -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct LNil; - -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct LCons(pub H, pub T); - impl<'lua> ToLuaMulti<'lua> for () { fn to_lua_multi(self, _: &'lua Lua) -> LuaResult { Ok(LuaMultiValue::new()) @@ -63,32 +59,32 @@ impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for LuaVariadic { } } -impl<'lua> ToLuaMulti<'lua> for LNil { +impl<'lua> ToLuaMulti<'lua> for HNil { fn to_lua_multi(self, _: &'lua Lua) -> LuaResult> { Ok(LuaMultiValue::new()) } } -impl<'lua> FromLuaMulti<'lua> for LNil { +impl<'lua> FromLuaMulti<'lua> for HNil { fn from_lua_multi(_: LuaMultiValue<'lua>, _: &'lua Lua) -> LuaResult { - Ok(LNil) + Ok(HNil) } } -impl<'lua, T: ToLuaMulti<'lua>> ToLuaMulti<'lua> for LCons { +impl<'lua, T: ToLuaMulti<'lua>> ToLuaMulti<'lua> for HCons { fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult> { self.0.to_lua_multi(lua) } } -impl<'lua, T: FromLuaMulti<'lua>> FromLuaMulti<'lua> for LCons { +impl<'lua, T: FromLuaMulti<'lua>> FromLuaMulti<'lua> for HCons { fn from_lua_multi(values: LuaMultiValue<'lua>, lua: &'lua Lua) -> LuaResult { - Ok(LCons(T::from_lua_multi(values, lua)?, LNil)) + Ok(HCons(T::from_lua_multi(values, lua)?, HNil)) } } -impl<'lua, H: ToLua<'lua>, A, B> ToLuaMulti<'lua> for LCons> - where LCons: ToLuaMulti<'lua> +impl<'lua, H: ToLua<'lua>, A, B> ToLuaMulti<'lua> for HCons> + where HCons: ToLuaMulti<'lua> { fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult> { let mut results = self.1.to_lua_multi(lua)?; @@ -97,12 +93,12 @@ impl<'lua, H: ToLua<'lua>, A, B> ToLuaMulti<'lua> for LCons> } } -impl<'lua, H: FromLua<'lua>, A, B> FromLuaMulti<'lua> for LCons> - where LCons: FromLuaMulti<'lua> +impl<'lua, H: FromLua<'lua>, A, B> FromLuaMulti<'lua> for HCons> + where HCons: FromLuaMulti<'lua> { fn from_lua_multi(mut values: LuaMultiValue<'lua>, lua: &'lua Lua) -> LuaResult { let val = H::from_lua(values.pop_front().unwrap_or(LuaNil), lua)?; - let res = LCons::::from_lua_multi(values, lua)?; - Ok(LCons(val, res)) + let res = HCons::::from_lua_multi(values, lua)?; + Ok(HCons(val, res)) } } diff --git a/src/tests.rs b/src/tests.rs index b9d85c6..3fd3d82 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -86,7 +86,7 @@ fn test_function() { .unwrap(); let concat = lua.get::<_, LuaFunction>("concat").unwrap(); - assert_eq!(concat.call::<_, String>(lua_multi!["foo", "bar"]).unwrap(), + assert_eq!(concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(), "foobar"); } @@ -108,8 +108,8 @@ fn test_bind() { let mut concat = lua.get::<_, LuaFunction>("concat").unwrap(); concat = concat.bind("foo").unwrap(); concat = concat.bind("bar").unwrap(); - concat = concat.bind(lua_multi!["baz", "baf"]).unwrap(); - assert_eq!(concat.call::<_, String>(lua_multi!["hi", "wut"]).unwrap(), + concat = concat.bind(hlist!["baz", "baf"]).unwrap(); + assert_eq!(concat.call::<_, String>(hlist!["hi", "wut"]).unwrap(), "foobarbazbafhiwut"); } @@ -202,11 +202,11 @@ fn test_metamethods() { fn add_methods(methods: &mut LuaUserDataMethods) { methods.add_method("get", |lua, data, _| lua.pack(data.0)); methods.add_meta_function(LuaMetaMethod::Add, |lua, args| { - let lua_multi_pat![lhs, rhs] = lua.unpack::(args)?; + let hlist_pat![lhs, rhs] = lua.unpack::(args)?; lua.pack(UserData(lhs.0 + rhs.0)) }); methods.add_meta_function(LuaMetaMethod::Sub, |lua, args| { - let lua_multi_pat![lhs, rhs] = lua.unpack::(args)?; + let hlist_pat![lhs, rhs] = lua.unpack::(args)?; lua.pack(UserData(lhs.0 - rhs.0)) }); methods.add_meta_method(LuaMetaMethod::Index, |lua, data, args| { @@ -282,11 +282,11 @@ fn test_lua_multi() { let concat = lua.get::<_, LuaFunction>("concat").unwrap(); let mreturn = lua.get::<_, LuaFunction>("mreturn").unwrap(); - assert_eq!(concat.call::<_, String>(lua_multi!["foo", "bar"]).unwrap(), + assert_eq!(concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(), "foobar"); - let lua_multi_pat![a, b] = mreturn.call::<_, LuaMulti![u64, u64]>(lua_multi![]).unwrap(); + let hlist_pat![a, b] = mreturn.call::<_, HList![u64, u64]>(hlist![]).unwrap(); assert_eq!((a, b), (1, 2)); - let lua_multi_pat![a, b, LuaVariadic(v)] = mreturn.call::<_, LuaMulti![u64, u64, LuaVariadic]>(lua_multi![]).unwrap(); + let hlist_pat![a, b, LuaVariadic(v)] = mreturn.call::<_, HList![u64, u64, LuaVariadic]>(hlist![]).unwrap(); assert_eq!((a, b), (1, 2)); assert_eq!(v, vec![3, 4, 5, 6]); } diff --git a/src/util.rs b/src/util.rs index 0eb5abd..99b6733 100644 --- a/src/util.rs +++ b/src/util.rs @@ -8,6 +8,12 @@ use std::panic::{catch_unwind, resume_unwind, UnwindSafe}; use ffi; use error::{LuaResult, LuaError, LuaErrorKind}; +macro_rules! cstr { + ($s:expr) => ( + concat!($s, "\0") as *const str as *const [c_char] as *const c_char + ); +} + // Run an operation on a lua_State and automatically clean up the stack before returning. Takes // the lua_State, the expected stack size change, and an operation to run. If the operation // results in success, then the stack is inspected to make sure the change in stack size matches @@ -139,7 +145,7 @@ pub unsafe fn pcall_with_traceback(state: *mut ffi::lua_State, if !s.is_null() { ffi::luaL_traceback(state, state, s, 0); } else { - ffi::luaL_traceback(state, state, lua_cstr!(""), 0); + ffi::luaL_traceback(state, state, cstr!(""), 0); } } 1