Fix references to hlists in documentation, improve? Variadic usability
Also rename to/from/pack/unpack to pack/unpack/pack_multi/unpack_multi, I don't know if this makes their usage clearer, and it IS a bit confusing that I'm changing the meaning of the words 'pack' and 'unpack'
This commit is contained in:
parent
c1abc18066
commit
48bf35dc5b
|
@ -77,29 +77,28 @@ fn examples() -> Result<()> {
|
|||
let print: Function = globals.get("print")?;
|
||||
print.call::<_, ()>("hello from rust")?;
|
||||
|
||||
// This API handles variadics using Heterogeneous Lists. This is one way to
|
||||
// call a function with multiple parameters:
|
||||
// This API handles variadics using tuples. This is one way to call a function with multiple
|
||||
// parameters:
|
||||
|
||||
print.call::<_, ()>(("hello", "again", "from", "rust"))?;
|
||||
|
||||
// You can bind rust functions to lua as well
|
||||
|
||||
// You can bind rust functions to lua as well. Callbacks receive the lua state itself 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 set of parameters, in this
|
||||
// case, the function expects two string sequences.
|
||||
let check_equal = lua.create_function(|_, (list1, list2): (Vec<String>, Vec<String>)| {
|
||||
// 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 into MultiValue. In this
|
||||
// way, multiple values can also be returned to Lua. Again, this cannot
|
||||
// be inferred as part of the function signature due to the same
|
||||
// lifetime type signature limitations.
|
||||
// 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.
|
||||
Ok(list1 == list2)
|
||||
});
|
||||
globals.set("check_equal", check_equal)?;
|
||||
|
||||
// You can also accept variadic arguments to rust callbacks.
|
||||
// You can also accept runtime variadic arguments to rust callbacks.
|
||||
|
||||
let join = lua.create_function(|_, strings: Variadic<String>| {
|
||||
// (This is quadratic!, it's just an example!)
|
||||
Ok(strings.0.iter().fold("".to_owned(), |a, b| a + b))
|
||||
Ok(strings.iter().fold("".to_owned(), |a, b| a + b))
|
||||
});
|
||||
globals.set("join", join)?;
|
||||
|
||||
|
@ -139,9 +138,7 @@ fn examples() -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
let vec2_constructor = lua.create_function(|_, (x, y): (f32, f32)| {
|
||||
Ok(Vec2(x, y))
|
||||
});
|
||||
let vec2_constructor = lua.create_function(|_, (x, y): (f32, f32)| Ok(Vec2(x, y)));
|
||||
globals.set("vec2", vec2_constructor)?;
|
||||
|
||||
assert!(
|
||||
|
|
31
src/lua.rs
31
src/lua.rs
|
@ -39,12 +39,10 @@ pub enum Value<'lua> {
|
|||
Function(Function<'lua>),
|
||||
/// Reference to a Lua thread (or coroutine).
|
||||
Thread(Thread<'lua>),
|
||||
/// Reference to a userdata object that holds a custom type which implements
|
||||
/// `UserData`. Special builtin userdata types will be represented as
|
||||
/// other `Value` variants.
|
||||
/// Reference to a userdata object that holds a custom type which implements `UserData`.
|
||||
/// Special builtin userdata types will be represented as other `Value` variants.
|
||||
UserData(AnyUserData<'lua>),
|
||||
/// `Error` is a special builtin userdata type. When received from Lua
|
||||
/// it is implicitly cloned.
|
||||
/// `Error` is a special builtin userdata type. When received from Lua it is implicitly cloned.
|
||||
Error(Error),
|
||||
}
|
||||
pub use self::Value::Nil;
|
||||
|
@ -1518,7 +1516,7 @@ impl Lua {
|
|||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Use the `hlist_macro` crate to use multiple arguments:
|
||||
/// Use tuples to accept multiple arguments:
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate rlua;
|
||||
|
@ -1674,25 +1672,26 @@ impl Lua {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result<Value<'lua>> {
|
||||
/// Converts a value that implements `ToLua` into a `Value` instance.
|
||||
pub fn pack<'lua, T: ToLua<'lua>>(&'lua self, t: T) -> Result<Value<'lua>> {
|
||||
t.to_lua(self)
|
||||
}
|
||||
|
||||
pub fn to<'lua, T: FromLua<'lua>>(&'lua self, value: Value<'lua>) -> Result<T> {
|
||||
/// Converts a `Value` instance into a value that implements `FromLua`.
|
||||
pub fn unpack<'lua, T: FromLua<'lua>>(&'lua self, value: Value<'lua>) -> Result<T> {
|
||||
T::from_lua(value, self)
|
||||
}
|
||||
|
||||
/// Packs up a value that implements `ToLuaMulti` into a `MultiValue` instance.
|
||||
///
|
||||
/// This can be used to return arbitrary Lua values from a Rust function back to Lua.
|
||||
pub fn pack<'lua, T: ToLuaMulti<'lua>>(&'lua self, t: T) -> Result<MultiValue<'lua>> {
|
||||
/// Converts a value that implements `ToLuaMulti` into a `MultiValue` instance.
|
||||
pub fn pack_multi<'lua, T: ToLuaMulti<'lua>>(&'lua self, t: T) -> Result<MultiValue<'lua>> {
|
||||
t.to_lua_multi(self)
|
||||
}
|
||||
|
||||
/// Unpacks a `MultiValue` instance into a value that implements `FromLuaMulti`.
|
||||
///
|
||||
/// This can be used to convert the arguments of a Rust function called by Lua.
|
||||
pub fn unpack<'lua, T: FromLuaMulti<'lua>>(&'lua self, value: MultiValue<'lua>) -> Result<T> {
|
||||
/// Converts a `MultiValue` instance into a value that implements `FromLuaMulti`.
|
||||
pub fn unpack_multi<'lua, T: FromLuaMulti<'lua>>(
|
||||
&'lua self,
|
||||
value: MultiValue<'lua>,
|
||||
) -> Result<T> {
|
||||
T::from_lua_multi(value, self)
|
||||
}
|
||||
|
||||
|
|
44
src/multi.rs
44
src/multi.rs
|
@ -1,3 +1,5 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::iter::FromIterator;
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
use error::*;
|
||||
|
@ -49,9 +51,45 @@ impl<'lua> FromLuaMulti<'lua> for MultiValue<'lua> {
|
|||
|
||||
/// Can be used to pass variadic values to or receive variadic values from Lua, where the type of
|
||||
/// the values is all the same and the number of values is defined at runtime. This can be included
|
||||
/// in an hlist when unpacking, but must be the final entry, and will consume the rest of the
|
||||
/// in tuple when unpacking, but must be the final entry, and will consume the rest of the
|
||||
/// parameters given.
|
||||
pub struct Variadic<T>(pub Vec<T>);
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Variadic<T>(Vec<T>);
|
||||
|
||||
impl<T> Variadic<T> {
|
||||
pub fn new() -> Variadic<T> {
|
||||
Variadic(Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FromIterator<T> for Variadic<T> {
|
||||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
||||
Variadic(Vec::from_iter(iter))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for Variadic<T> {
|
||||
type Item = T;
|
||||
type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Variadic<T> {
|
||||
type Target = Vec<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for Variadic<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua, T: ToLua<'lua>> ToLuaMulti<'lua> for Variadic<T> {
|
||||
fn to_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
|
@ -128,7 +166,7 @@ macro_rules! push_reverse {
|
|||
($multi_value:expr,) => ();
|
||||
}
|
||||
|
||||
impl_tuple! { }
|
||||
impl_tuple!{}
|
||||
impl_tuple! { A }
|
||||
impl_tuple! { A B }
|
||||
impl_tuple! { A B C }
|
||||
|
|
17
src/tests.rs
17
src/tests.rs
|
@ -220,9 +220,7 @@ fn test_rust_function() {
|
|||
).unwrap();
|
||||
|
||||
let lua_function = globals.get::<_, Function>("lua_function").unwrap();
|
||||
let rust_function = lua.create_function(|_, _: ()| {
|
||||
Ok("hello")
|
||||
});
|
||||
let rust_function = lua.create_function(|_, _: ()| Ok("hello"));
|
||||
|
||||
globals.set("rust_function", rust_function).unwrap();
|
||||
assert_eq!(lua_function.call::<_, String>(()).unwrap(), "hello");
|
||||
|
@ -303,13 +301,14 @@ fn test_metamethods() {
|
|||
methods.add_meta_function(MetaMethod::Sub, |_, (lhs, rhs): (MyUserData, MyUserData)| {
|
||||
Ok(MyUserData(lhs.0 - rhs.0))
|
||||
});
|
||||
methods.add_meta_method(MetaMethod::Index, |_, data, index: LuaString| {
|
||||
if index.to_str()? == "inner" {
|
||||
methods.add_meta_method(
|
||||
MetaMethod::Index,
|
||||
|_, data, index: LuaString| if index.to_str()? == "inner" {
|
||||
Ok(data.0)
|
||||
} else {
|
||||
Err("no such custom index".to_lua_err())
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,9 +381,9 @@ fn test_lua_multi() {
|
|||
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
||||
let (a, b) = mreturn.call::<_, (u64, u64)>(()).unwrap();
|
||||
assert_eq!((a, b), (1, 2));
|
||||
let (a, b, Variadic(v)) = mreturn.call::<_, (u64, u64, Variadic<u64>)>(()).unwrap();
|
||||
let (a, b, v) = mreturn.call::<_, (u64, u64, Variadic<u64>)>(()).unwrap();
|
||||
assert_eq!((a, b), (1, 2));
|
||||
assert_eq!(v, vec![3, 4, 5, 6]);
|
||||
assert_eq!(v[..], [3, 4, 5, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in New Issue