Update to use hlist_macro for hlist macros.

You will type hlist! hlist_pat! and HList! so often that every character
counts.  Apologize for the API churn in the README.
This commit is contained in:
kyren 2017-05-22 03:09:59 -04:00
parent 9bed8f499f
commit b15ee9053e
7 changed files with 52 additions and 37 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "rlua" name = "rlua"
version = "0.1.0" version = "0.2.0"
authors = ["kyren <catherine@chucklefish.org>"] authors = ["kyren <catherine@chucklefish.org>"]
repository = "https://github.com/chucklefish/rlua" repository = "https://github.com/chucklefish/rlua"
description = "High level bindings to Lua 5.3" description = "High level bindings to Lua 5.3"
@ -9,7 +9,8 @@ keywords = ["lua"]
license = "MIT" license = "MIT"
[build-dependencies] [build-dependencies]
gcc = "*" gcc = "0.3"
[dependencies] [dependencies]
error-chain = "*" hlist-macro = "0.1"
error-chain = "0.10"

View File

@ -65,6 +65,12 @@ in rustc. For example:
See [this reddit discussion](http://www.reddit.com/r/rust/comments/5yujt6/) for See [this reddit discussion](http://www.reddit.com/r/rust/comments/5yujt6/) for
details of the current lifetime problem with callback wrapping. 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 ## Safety
My *goal* is complete safety, it should not be possible to cause undefined 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. are so many ways to cause unsafety with Lua that it just needs more testing.
## Examples ## Examples
Please look at the examples [here](examples/examples.rs). Please look at the examples [here](examples/examples.rs).

View File

@ -1,4 +1,5 @@
#[macro_use] #[macro_use]
extern crate hlist_macro;
extern crate rlua; extern crate rlua;
use rlua::*; use rlua::*;
@ -70,7 +71,7 @@ fn examples() -> LuaResult<()> {
// is one way to call a function with multiple parameters: // is one way to call a function with multiple parameters:
print print
.call::<_, ()>(lua_multi!["hello", "again", "from", "rust"])?; .call::<_, ()>(hlist!["hello", "again", "from", "rust"])?;
// You can bind rust functions to lua as well // 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 // 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 // function signature, but this will be fixed with ATCs. Notice the use of the hlist
// macros again. // macros again.
let lua_multi_pat![list1, list2] = lua.unpack::<LuaMulti![Vec<String>, Vec<String>]>(args)?; let hlist_pat![list1, list2] = lua.unpack::<HList![Vec<String>, Vec<String>]>(args)?;
// This function just checks whether two string lists are equal, and in an inefficient way. // 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 // 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| { methods.add_meta_function(LuaMetaMethod::Add, |lua, params| {
let lua_multi_pat![vec1, vec2] = lua.unpack::<LuaMulti![Vec2, Vec2]>(params)?; let hlist_pat![vec1, vec2] = lua.unpack::<HList![Vec2, Vec2]>(params)?;
lua.pack(Vec2(vec1.0 + vec2.0, vec1.1 + vec2.1)) lua.pack(Vec2(vec1.0 + vec2.0, vec1.1 + vec2.1))
}); });
} }
} }
let vec2_constructor = lua.create_function(|lua, args| { let vec2_constructor = lua.create_function(|lua, args| {
let lua_multi_pat![x, y] = lua.unpack::<LuaMulti![f32, f32]>(args)?; let hlist_pat![x, y] = lua.unpack::<HList![f32, f32]>(args)?;
lua.pack(Vec2(x, y)) lua.pack(Vec2(x, y))
})?; })?;
lua.set("vec2", vec2_constructor)?; lua.set("vec2", vec2_constructor)?;

View File

@ -1,10 +1,14 @@
#[cfg(test)]
#[macro_use]
extern crate hlist_macro;
#[cfg(not(test))]
extern crate hlist_macro;
#[macro_use] #[macro_use]
extern crate error_chain; extern crate error_chain;
pub mod ffi; pub mod ffi;
#[macro_use]
mod macros;
mod util; mod util;
mod error; mod error;
mod lua; mod lua;

View File

@ -1,12 +1,8 @@
use hlist_macro::{HNil, HCons};
use error::*; use error::*;
use lua::*; 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<H, T>(pub H, pub T);
impl<'lua> ToLuaMulti<'lua> for () { impl<'lua> ToLuaMulti<'lua> for () {
fn to_lua_multi(self, _: &'lua Lua) -> LuaResult<LuaMultiValue> { fn to_lua_multi(self, _: &'lua Lua) -> LuaResult<LuaMultiValue> {
Ok(LuaMultiValue::new()) Ok(LuaMultiValue::new())
@ -63,32 +59,32 @@ impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for LuaVariadic<T> {
} }
} }
impl<'lua> ToLuaMulti<'lua> for LNil { impl<'lua> ToLuaMulti<'lua> for HNil {
fn to_lua_multi(self, _: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> { fn to_lua_multi(self, _: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> {
Ok(LuaMultiValue::new()) Ok(LuaMultiValue::new())
} }
} }
impl<'lua> FromLuaMulti<'lua> for LNil { impl<'lua> FromLuaMulti<'lua> for HNil {
fn from_lua_multi(_: LuaMultiValue<'lua>, _: &'lua Lua) -> LuaResult<Self> { fn from_lua_multi(_: LuaMultiValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
Ok(LNil) Ok(HNil)
} }
} }
impl<'lua, T: ToLuaMulti<'lua>> ToLuaMulti<'lua> for LCons<T, LNil> { impl<'lua, T: ToLuaMulti<'lua>> ToLuaMulti<'lua> for HCons<T, HNil> {
fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> { fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> {
self.0.to_lua_multi(lua) self.0.to_lua_multi(lua)
} }
} }
impl<'lua, T: FromLuaMulti<'lua>> FromLuaMulti<'lua> for LCons<T, LNil> { impl<'lua, T: FromLuaMulti<'lua>> FromLuaMulti<'lua> for HCons<T, HNil> {
fn from_lua_multi(values: LuaMultiValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> { fn from_lua_multi(values: LuaMultiValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> {
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<H, LCons<A, B>> impl<'lua, H: ToLua<'lua>, A, B> ToLuaMulti<'lua> for HCons<H, HCons<A, B>>
where LCons<A, B>: ToLuaMulti<'lua> where HCons<A, B>: ToLuaMulti<'lua>
{ {
fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> { fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> {
let mut results = self.1.to_lua_multi(lua)?; let mut results = self.1.to_lua_multi(lua)?;
@ -97,12 +93,12 @@ impl<'lua, H: ToLua<'lua>, A, B> ToLuaMulti<'lua> for LCons<H, LCons<A, B>>
} }
} }
impl<'lua, H: FromLua<'lua>, A, B> FromLuaMulti<'lua> for LCons<H, LCons<A, B>> impl<'lua, H: FromLua<'lua>, A, B> FromLuaMulti<'lua> for HCons<H, HCons<A, B>>
where LCons<A, B>: FromLuaMulti<'lua> where HCons<A, B>: FromLuaMulti<'lua>
{ {
fn from_lua_multi(mut values: LuaMultiValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> { fn from_lua_multi(mut values: LuaMultiValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> {
let val = H::from_lua(values.pop_front().unwrap_or(LuaNil), lua)?; let val = H::from_lua(values.pop_front().unwrap_or(LuaNil), lua)?;
let res = LCons::<A, B>::from_lua_multi(values, lua)?; let res = HCons::<A, B>::from_lua_multi(values, lua)?;
Ok(LCons(val, res)) Ok(HCons(val, res))
} }
} }

View File

@ -86,7 +86,7 @@ fn test_function() {
.unwrap(); .unwrap();
let concat = lua.get::<_, LuaFunction>("concat").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"); "foobar");
} }
@ -108,8 +108,8 @@ fn test_bind() {
let mut concat = lua.get::<_, LuaFunction>("concat").unwrap(); let mut concat = lua.get::<_, LuaFunction>("concat").unwrap();
concat = concat.bind("foo").unwrap(); concat = concat.bind("foo").unwrap();
concat = concat.bind("bar").unwrap(); concat = concat.bind("bar").unwrap();
concat = concat.bind(lua_multi!["baz", "baf"]).unwrap(); concat = concat.bind(hlist!["baz", "baf"]).unwrap();
assert_eq!(concat.call::<_, String>(lua_multi!["hi", "wut"]).unwrap(), assert_eq!(concat.call::<_, String>(hlist!["hi", "wut"]).unwrap(),
"foobarbazbafhiwut"); "foobarbazbafhiwut");
} }
@ -202,11 +202,11 @@ fn test_metamethods() {
fn add_methods(methods: &mut LuaUserDataMethods<Self>) { fn add_methods(methods: &mut LuaUserDataMethods<Self>) {
methods.add_method("get", |lua, data, _| lua.pack(data.0)); methods.add_method("get", |lua, data, _| lua.pack(data.0));
methods.add_meta_function(LuaMetaMethod::Add, |lua, args| { methods.add_meta_function(LuaMetaMethod::Add, |lua, args| {
let lua_multi_pat![lhs, rhs] = lua.unpack::<LuaMulti![UserData, UserData]>(args)?; let hlist_pat![lhs, rhs] = lua.unpack::<HList![UserData, UserData]>(args)?;
lua.pack(UserData(lhs.0 + rhs.0)) lua.pack(UserData(lhs.0 + rhs.0))
}); });
methods.add_meta_function(LuaMetaMethod::Sub, |lua, args| { methods.add_meta_function(LuaMetaMethod::Sub, |lua, args| {
let lua_multi_pat![lhs, rhs] = lua.unpack::<LuaMulti![UserData, UserData]>(args)?; let hlist_pat![lhs, rhs] = lua.unpack::<HList![UserData, UserData]>(args)?;
lua.pack(UserData(lhs.0 - rhs.0)) lua.pack(UserData(lhs.0 - rhs.0))
}); });
methods.add_meta_method(LuaMetaMethod::Index, |lua, data, args| { 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 concat = lua.get::<_, LuaFunction>("concat").unwrap();
let mreturn = lua.get::<_, LuaFunction>("mreturn").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"); "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)); assert_eq!((a, b), (1, 2));
let lua_multi_pat![a, b, LuaVariadic(v)] = mreturn.call::<_, LuaMulti![u64, u64, LuaVariadic<u64>]>(lua_multi![]).unwrap(); let hlist_pat![a, b, LuaVariadic(v)] = mreturn.call::<_, HList![u64, u64, LuaVariadic<u64>]>(hlist![]).unwrap();
assert_eq!((a, b), (1, 2)); assert_eq!((a, b), (1, 2));
assert_eq!(v, vec![3, 4, 5, 6]); assert_eq!(v, vec![3, 4, 5, 6]);
} }

View File

@ -8,6 +8,12 @@ use std::panic::{catch_unwind, resume_unwind, UnwindSafe};
use ffi; use ffi;
use error::{LuaResult, LuaError, LuaErrorKind}; 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 // 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 // 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 // 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() { if !s.is_null() {
ffi::luaL_traceback(state, state, s, 0); ffi::luaL_traceback(state, state, s, 0);
} else { } else {
ffi::luaL_traceback(state, state, lua_cstr!("<unprintable error>"), 0); ffi::luaL_traceback(state, state, cstr!("<unprintable error>"), 0);
} }
} }
1 1