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]
name = "rlua"
version = "0.1.0"
version = "0.2.0"
authors = ["kyren <catherine@chucklefish.org>"]
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"

View file

@ -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).

View file

@ -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::<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.
// 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::<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))
});
}
}
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.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]
extern crate error_chain;
pub mod ffi;
#[macro_use]
mod macros;
mod util;
mod error;
mod lua;

View file

@ -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<H, T>(pub H, pub T);
impl<'lua> ToLuaMulti<'lua> for () {
fn to_lua_multi(self, _: &'lua Lua) -> LuaResult<LuaMultiValue> {
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>> {
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> {
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>> {
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> {
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>>
where LCons<A, B>: ToLuaMulti<'lua>
impl<'lua, H: ToLua<'lua>, A, B> ToLuaMulti<'lua> for HCons<H, HCons<A, B>>
where HCons<A, B>: ToLuaMulti<'lua>
{
fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'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>>
where LCons<A, B>: FromLuaMulti<'lua>
impl<'lua, H: FromLua<'lua>, A, B> FromLuaMulti<'lua> for HCons<H, HCons<A, B>>
where HCons<A, B>: FromLuaMulti<'lua>
{
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 res = LCons::<A, B>::from_lua_multi(values, lua)?;
Ok(LCons(val, res))
let res = HCons::<A, B>::from_lua_multi(values, lua)?;
Ok(HCons(val, res))
}
}

View file

@ -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<Self>) {
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::<LuaMulti![UserData, UserData]>(args)?;
let hlist_pat![lhs, rhs] = lua.unpack::<HList![UserData, UserData]>(args)?;
lua.pack(UserData(lhs.0 + rhs.0))
});
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))
});
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<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!(v, vec![3, 4, 5, 6]);
}

View file

@ -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!("<unprintable error>"), 0);
ffi::luaL_traceback(state, state, cstr!("<unprintable error>"), 0);
}
}
1