Two major API changes to start with:
* Callbacks have generic argument and return types * All variadics are done with tuples
This commit is contained in:
parent
8ba3886c96
commit
4549abbb85
|
@ -20,6 +20,3 @@ builtin-lua = ["gcc"]
|
|||
|
||||
[build-dependencies]
|
||||
gcc = { version = "0.3", optional = true }
|
||||
|
||||
[dependencies]
|
||||
hlist-macro = "0.1"
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#[macro_use]
|
||||
extern crate hlist_macro;
|
||||
extern crate rlua;
|
||||
|
||||
use std::f32;
|
||||
|
@ -82,9 +80,7 @@ fn examples() -> Result<()> {
|
|||
// This API handles variadics using Heterogeneous Lists. This is one way to
|
||||
// call a function with multiple parameters:
|
||||
|
||||
print.call::<_, ()>(
|
||||
hlist!["hello", "again", "from", "rust"],
|
||||
)?;
|
||||
print.call::<_, ()>(("hello", "again", "from", "rust"))?;
|
||||
|
||||
// You can bind rust functions to lua as well
|
||||
|
||||
|
@ -95,7 +91,7 @@ fn examples() -> Result<()> {
|
|||
// 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 hlist_pat![list1, list2] = lua.unpack::<HList![Vec<String>, Vec<String>]>(args)?;
|
||||
let (list1, list2) = lua.unpack::<(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
|
||||
|
@ -141,20 +137,20 @@ fn examples() -> Result<()> {
|
|||
|
||||
impl UserData for Vec2 {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("magnitude", |lua, vec, _| {
|
||||
methods.add_method("magnitude", |lua, vec, _: ()| {
|
||||
let mag_squared = vec.0 * vec.0 + vec.1 * vec.1;
|
||||
lua.pack(mag_squared.sqrt())
|
||||
});
|
||||
|
||||
methods.add_meta_function(MetaMethod::Add, |lua, params| {
|
||||
let hlist_pat![vec1, vec2] = lua.unpack::<HList![Vec2, Vec2]>(params)?;
|
||||
let (vec1, vec2) = lua.unpack::<(Vec2, Vec2)>(params)?;
|
||||
lua.pack(Vec2(vec1.0 + vec2.0, vec1.1 + vec2.1))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let vec2_constructor = lua.create_function(|lua, args| {
|
||||
let hlist_pat![x, y] = lua.unpack::<HList![f32, f32]>(args)?;
|
||||
let (x, y) = lua.unpack::<(f32, f32)>(args)?;
|
||||
lua.pack(Vec2(x, y))
|
||||
});
|
||||
globals.set("vec2", vec2_constructor)?;
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
// Deny warnings inside doc tests / examples
|
||||
#![doc(test(attr(deny(warnings))))]
|
||||
|
||||
#[cfg_attr(test, macro_use)]
|
||||
extern crate hlist_macro;
|
||||
|
||||
pub mod ffi;
|
||||
#[macro_use]
|
||||
mod util;
|
||||
|
|
107
src/lua.rs
107
src/lua.rs
|
@ -647,7 +647,6 @@ impl<'lua> Function<'lua> {
|
|||
///
|
||||
/// ```
|
||||
/// # extern crate rlua;
|
||||
/// # #[macro_use] extern crate hlist_macro;
|
||||
/// # use rlua::{Lua, Function, Result};
|
||||
/// # fn try_main() -> Result<()> {
|
||||
/// let lua = Lua::new();
|
||||
|
@ -658,7 +657,7 @@ impl<'lua> Function<'lua> {
|
|||
/// end
|
||||
/// "#, None)?;
|
||||
///
|
||||
/// assert_eq!(sum.call::<_, u32>(hlist![3, 4])?, 3 + 4);
|
||||
/// assert_eq!(sum.call::<_, u32>((3, 4))?, 3 + 4);
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
|
@ -966,9 +965,11 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
///
|
||||
/// If `add_meta_method` is used to override the `__index` metamethod, this approach will fall
|
||||
/// back to the user-provided metamethod if no regular method was found.
|
||||
pub fn add_method<M>(&mut self, name: &str, method: M)
|
||||
pub fn add_method<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a T, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a T, A) -> Result<R>,
|
||||
{
|
||||
self.methods.insert(
|
||||
name.to_owned(),
|
||||
|
@ -981,9 +982,11 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
/// Refer to [`add_method`] for more information about the implementation.
|
||||
///
|
||||
/// [`add_method`]: #method.add_method
|
||||
pub fn add_method_mut<M>(&mut self, name: &str, method: M)
|
||||
pub fn add_method_mut<A, R, M>(&mut self, name: &str, method: M)
|
||||
where
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a mut T, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a mut T, A) -> Result<R>,
|
||||
{
|
||||
self.methods.insert(
|
||||
name.to_owned(),
|
||||
|
@ -998,11 +1001,16 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
///
|
||||
/// [`add_method`]: #method.add_method
|
||||
/// [`add_method_mut`]: #method.add_method_mut
|
||||
pub fn add_function<F>(&mut self, name: &str, function: F)
|
||||
pub fn add_function<A, R, F>(&mut self, name: &str, function: F)
|
||||
where
|
||||
F: 'lua + FnMut(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
F: 'lua + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.methods.insert(name.to_owned(), Box::new(function));
|
||||
self.methods.insert(
|
||||
name.to_owned(),
|
||||
Self::box_function(function),
|
||||
);
|
||||
}
|
||||
|
||||
/// Add a metamethod which accepts a `&T` as the first parameter.
|
||||
|
@ -1013,9 +1021,11 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
/// side has a metatable. To prevent this, use [`add_meta_function`].
|
||||
///
|
||||
/// [`add_meta_function`]: #method.add_meta_function
|
||||
pub fn add_meta_method<M>(&mut self, meta: MetaMethod, method: M)
|
||||
pub fn add_meta_method<A, R, M>(&mut self, meta: MetaMethod, method: M)
|
||||
where
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a T, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a T, A) -> Result<R>,
|
||||
{
|
||||
self.meta_methods.insert(meta, Self::box_method(method));
|
||||
}
|
||||
|
@ -1028,9 +1038,11 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
/// side has a metatable. To prevent this, use [`add_meta_function`].
|
||||
///
|
||||
/// [`add_meta_function`]: #method.add_meta_function
|
||||
pub fn add_meta_method_mut<M>(&mut self, meta: MetaMethod, method: M)
|
||||
pub fn add_meta_method_mut<A, R, M>(&mut self, meta: MetaMethod, method: M)
|
||||
where
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a mut T, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a mut T, A) -> Result<R>,
|
||||
{
|
||||
self.meta_methods.insert(meta, Self::box_method_mut(method));
|
||||
}
|
||||
|
@ -1040,21 +1052,39 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
/// Metamethods for binary operators can be triggered if either the left or right argument to
|
||||
/// the binary operator has a metatable, so the first argument here is not necessarily a
|
||||
/// userdata of type `T`.
|
||||
pub fn add_meta_function<F>(&mut self, meta: MetaMethod, function: F)
|
||||
pub fn add_meta_function<A, R, F>(&mut self, meta: MetaMethod, function: F)
|
||||
where
|
||||
F: 'lua + FnMut(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
F: 'lua + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.meta_methods.insert(meta, Box::new(function));
|
||||
self.meta_methods.insert(meta, Self::box_function(function));
|
||||
}
|
||||
|
||||
fn box_method<M>(mut method: M) -> Callback<'lua>
|
||||
fn box_function<A, R, F>(mut function: F) -> Callback<'lua>
|
||||
where
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a T, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
F: 'lua + for<'a> FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
Box::new(move |lua, args| {
|
||||
function(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(
|
||||
lua,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn box_method<A, R, M>(mut method: M) -> Callback<'lua>
|
||||
where
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a T, A) -> Result<R>,
|
||||
{
|
||||
Box::new(move |lua, mut args| if let Some(front) = args.pop_front() {
|
||||
let userdata = AnyUserData::from_lua(front, lua)?;
|
||||
let userdata = userdata.borrow::<T>()?;
|
||||
method(lua, &userdata, args)
|
||||
method(lua, &userdata, A::from_lua_multi(args, lua)?)?
|
||||
.to_lua_multi(lua)
|
||||
} else {
|
||||
Err(Error::FromLuaConversionError(
|
||||
"No userdata supplied as first argument to method"
|
||||
|
@ -1063,14 +1093,17 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
})
|
||||
}
|
||||
|
||||
fn box_method_mut<M>(mut method: M) -> Callback<'lua>
|
||||
fn box_method_mut<A, R, M>(mut method: M) -> Callback<'lua>
|
||||
where
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a mut T, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
M: 'lua + for<'a> FnMut(&'lua Lua, &'a mut T, A) -> Result<R>,
|
||||
{
|
||||
Box::new(move |lua, mut args| if let Some(front) = args.pop_front() {
|
||||
let userdata = AnyUserData::from_lua(front, lua)?;
|
||||
let mut userdata = userdata.borrow_mut::<T>()?;
|
||||
method(lua, &mut userdata, args)
|
||||
method(lua, &mut userdata, A::from_lua_multi(args, lua)?)?
|
||||
.to_lua_multi(lua)
|
||||
} else {
|
||||
Err(
|
||||
Error::FromLuaConversionError(
|
||||
|
@ -1078,7 +1111,6 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
).into(),
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1121,21 +1153,17 @@ impl<'lua, T: UserData> UserDataMethods<'lua, T> {
|
|||
///
|
||||
/// impl UserData for MyUserData {
|
||||
/// fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
/// methods.add_method("get", |lua, this, args| {
|
||||
/// # let _ = (lua, args); // used
|
||||
/// lua.pack(this.0)
|
||||
/// methods.add_method("get", |_, this, _: ()| {
|
||||
/// Ok(this.0)
|
||||
/// });
|
||||
///
|
||||
/// methods.add_method_mut("add", |lua, this, args| {
|
||||
/// let value: i32 = lua.unpack(args)?;
|
||||
///
|
||||
/// methods.add_method_mut("add", |_, this, value: i32| {
|
||||
/// this.0 += value;
|
||||
/// lua.pack(())
|
||||
/// Ok(())
|
||||
/// });
|
||||
///
|
||||
/// methods.add_meta_method(MetaMethod::Add, |lua, this, args| {
|
||||
/// let value: i32 = lua.unpack(args)?;
|
||||
/// lua.pack(this.0 + value)
|
||||
/// methods.add_meta_method(MetaMethod::Add, |_, this, value: i32| {
|
||||
/// Ok(this.0 + value)
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
|
@ -1494,14 +1522,13 @@ impl Lua {
|
|||
/// Use the `hlist_macro` crate to use multiple arguments:
|
||||
///
|
||||
/// ```
|
||||
/// #[macro_use] extern crate hlist_macro;
|
||||
/// # extern crate rlua;
|
||||
/// # use rlua::{Lua, Result};
|
||||
/// # fn try_main() -> Result<()> {
|
||||
/// let lua = Lua::new();
|
||||
///
|
||||
/// let print_person = lua.create_function(|lua, args| {
|
||||
/// let hlist_pat![name, age]: HList![String, u8] = lua.unpack(args)?;
|
||||
/// let (name, age): (String, u8) = lua.unpack(args)?;
|
||||
/// println!("{} is {} years old!", name, age);
|
||||
/// lua.pack(())
|
||||
/// });
|
||||
|
@ -1512,11 +1539,15 @@ impl Lua {
|
|||
/// # try_main().unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn create_function<'lua, F>(&'lua self, func: F) -> Function<'lua>
|
||||
pub fn create_function<'lua, A, R, F>(&'lua self, mut func: F) -> Function<'lua>
|
||||
where
|
||||
F: 'lua + FnMut(&'lua Lua, MultiValue<'lua>) -> Result<MultiValue<'lua>>,
|
||||
A: 'lua + FromLuaMulti<'lua>,
|
||||
R: 'lua + ToLuaMulti<'lua>,
|
||||
F: 'lua + FnMut(&'lua Lua, A) -> Result<R>,
|
||||
{
|
||||
self.create_callback_function(Box::new(func))
|
||||
self.create_callback_function(Box::new(move |lua, args| {
|
||||
func(lua, A::from_lua_multi(args, lua)?)?.to_lua_multi(lua)
|
||||
}))
|
||||
}
|
||||
|
||||
/// Wraps a Lua function into a new thread (or coroutine).
|
||||
|
|
127
src/multi.rs
127
src/multi.rs
|
@ -1,22 +1,8 @@
|
|||
use std::result::Result as StdResult;
|
||||
|
||||
use hlist_macro::{HNil, HCons};
|
||||
|
||||
use error::*;
|
||||
use lua::*;
|
||||
|
||||
impl<'lua> ToLuaMulti<'lua> for () {
|
||||
fn to_lua_multi(self, _: &'lua Lua) -> Result<MultiValue> {
|
||||
Ok(MultiValue::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLuaMulti<'lua> for () {
|
||||
fn from_lua_multi(_: MultiValue, _: &'lua Lua) -> Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Result is convertible to `MultiValue` following the common lua idiom of returning the result
|
||||
/// on success, or in the case of an error, returning nil followed by the error
|
||||
impl<'lua, T: ToLua<'lua>, E: ToLua<'lua>> ToLuaMulti<'lua> for StdResult<T, E> {
|
||||
|
@ -83,48 +69,79 @@ impl<'lua, T: FromLua<'lua>> FromLuaMulti<'lua> for Variadic<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLuaMulti<'lua> for HNil {
|
||||
fn to_lua_multi(self, _: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
Ok(MultiValue::new())
|
||||
}
|
||||
macro_rules! impl_tuple {
|
||||
() => (
|
||||
impl<'lua> ToLuaMulti<'lua> for () {
|
||||
fn to_lua_multi(self, _: &'lua Lua) -> Result<MultiValue> {
|
||||
Ok(MultiValue::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLuaMulti<'lua> for () {
|
||||
fn from_lua_multi(_: MultiValue, _: &'lua Lua) -> Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
($last:ident $($name:ident)*) => (
|
||||
impl<'lua, $($name,)* $last> ToLuaMulti<'lua> for ($($name,)* $last,)
|
||||
where $($name: ToLua<'lua>,)*
|
||||
$last: ToLuaMulti<'lua>
|
||||
{
|
||||
#[allow(unused_mut)]
|
||||
#[allow(non_snake_case)]
|
||||
fn to_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
let ($($name,)* $last,) = self;
|
||||
|
||||
let mut results = $last.to_lua_multi(lua)?;
|
||||
push_reverse!(results, $($name.to_lua(lua)?,)*);
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua, $($name,)* $last> FromLuaMulti<'lua> for ($($name,)* $last,)
|
||||
where $($name: FromLua<'lua>,)*
|
||||
$last: FromLuaMulti<'lua>
|
||||
{
|
||||
#[allow(unused_mut)]
|
||||
#[allow(non_snake_case)]
|
||||
fn from_lua_multi(mut values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
|
||||
$(let $name = values.pop_front().unwrap_or(Nil);)*
|
||||
let $last = FromLuaMulti::from_lua_multi(values, lua)?;
|
||||
Ok(($(FromLua::from_lua($name, lua)?,)* $last,))
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl<'lua> FromLuaMulti<'lua> for HNil {
|
||||
fn from_lua_multi(_: MultiValue<'lua>, _: &'lua Lua) -> Result<Self> {
|
||||
Ok(HNil)
|
||||
}
|
||||
macro_rules! push_reverse {
|
||||
($multi_value:expr, $first:expr, $($rest:expr,)*) => (
|
||||
push_reverse!($multi_value, $($rest,)*);
|
||||
$multi_value.push_front($first);
|
||||
);
|
||||
|
||||
($multi_value:expr, $first:expr) => (
|
||||
$multi_value.push_front($first);
|
||||
);
|
||||
|
||||
($multi_value:expr,) => ();
|
||||
}
|
||||
|
||||
impl<'lua, T: ToLuaMulti<'lua>> ToLuaMulti<'lua> for HCons<T, HNil> {
|
||||
fn to_lua_multi(self, lua: &'lua Lua) -> Result<MultiValue<'lua>> {
|
||||
self.0.to_lua_multi(lua)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua, T: FromLuaMulti<'lua>> FromLuaMulti<'lua> for HCons<T, HNil> {
|
||||
fn from_lua_multi(values: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
|
||||
Ok(HCons(T::from_lua_multi(values, lua)?, HNil))
|
||||
}
|
||||
}
|
||||
|
||||
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) -> Result<MultiValue<'lua>> {
|
||||
let mut results = self.1.to_lua_multi(lua)?;
|
||||
results.push_front(self.0.to_lua(lua)?);
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
||||
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: MultiValue<'lua>, lua: &'lua Lua) -> Result<Self> {
|
||||
let val = H::from_lua(values.pop_front().unwrap_or(Nil), lua)?;
|
||||
let res = HCons::<A, B>::from_lua_multi(values, lua)?;
|
||||
Ok(HCons(val, res))
|
||||
}
|
||||
}
|
||||
impl_tuple! { }
|
||||
impl_tuple! { A }
|
||||
impl_tuple! { A B }
|
||||
impl_tuple! { A B C }
|
||||
impl_tuple! { A B C D }
|
||||
impl_tuple! { A B C D E }
|
||||
impl_tuple! { A B C D E F }
|
||||
impl_tuple! { A B C D E F G }
|
||||
impl_tuple! { A B C D E F G H }
|
||||
impl_tuple! { A B C D E F G H I }
|
||||
impl_tuple! { A B C D E F G H I J }
|
||||
impl_tuple! { A B C D E F G H I J K }
|
||||
impl_tuple! { A B C D E F G H I J K L }
|
||||
impl_tuple! { A B C D E F G H I J K L M }
|
||||
impl_tuple! { A B C D E F G H I J K L M N }
|
||||
impl_tuple! { A B C D E F G H I J K L M N O }
|
||||
impl_tuple! { A B C D E F G H I J K L M N O P }
|
||||
|
|
90
src/tests.rs
90
src/tests.rs
|
@ -173,10 +173,7 @@ fn test_function() {
|
|||
).unwrap();
|
||||
|
||||
let concat = globals.get::<_, Function>("concat").unwrap();
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(),
|
||||
"foobar"
|
||||
);
|
||||
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -199,9 +196,9 @@ fn test_bind() {
|
|||
let mut concat = globals.get::<_, Function>("concat").unwrap();
|
||||
concat = concat.bind("foo").unwrap();
|
||||
concat = concat.bind("bar").unwrap();
|
||||
concat = concat.bind(hlist!["baz", "baf"]).unwrap();
|
||||
concat = concat.bind(("baz", "baf")).unwrap();
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(hlist!["hi", "wut"]).unwrap(),
|
||||
concat.call::<_, String>(("hi", "wut")).unwrap(),
|
||||
"foobarbazbafhiwut"
|
||||
);
|
||||
}
|
||||
|
@ -225,9 +222,9 @@ fn test_rust_function() {
|
|||
).unwrap();
|
||||
|
||||
let lua_function = globals.get::<_, Function>("lua_function").unwrap();
|
||||
let rust_function = lua.create_function(|lua, _| {
|
||||
let rust_function = lua.create_function(|_, _: ()| {
|
||||
captured_var = 42;
|
||||
lua.pack("hello")
|
||||
Ok("hello")
|
||||
});
|
||||
|
||||
globals.set("rust_function", rust_function).unwrap();
|
||||
|
@ -264,10 +261,10 @@ fn test_methods() {
|
|||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("get_value", |lua, data, _| lua.pack(data.0));
|
||||
methods.add_method_mut("set_value", |lua, data, args| {
|
||||
data.0 = lua.unpack(args)?;
|
||||
lua.pack(())
|
||||
methods.add_method("get_value", |_, data, _: ()| Ok(data.0));
|
||||
methods.add_method_mut("set_value", |_, data, args| {
|
||||
data.0 = args;
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -304,19 +301,16 @@ fn test_metamethods() {
|
|||
|
||||
impl UserData for MyUserData {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("get", |lua, data, _| lua.pack(data.0));
|
||||
methods.add_meta_function(MetaMethod::Add, |lua, args| {
|
||||
let hlist_pat![lhs, rhs] = lua.unpack::<HList![MyUserData, MyUserData]>(args)?;
|
||||
lua.pack(MyUserData(lhs.0 + rhs.0))
|
||||
methods.add_method("get", |_, data, _: ()| Ok(data.0));
|
||||
methods.add_meta_function(MetaMethod::Add, |_, (lhs, rhs): (MyUserData, MyUserData)| {
|
||||
Ok(MyUserData(lhs.0 + rhs.0))
|
||||
});
|
||||
methods.add_meta_function(MetaMethod::Sub, |lua, args| {
|
||||
let hlist_pat![lhs, rhs] = lua.unpack::<HList![MyUserData, MyUserData]>(args)?;
|
||||
lua.pack(MyUserData(lhs.0 - rhs.0))
|
||||
methods.add_meta_function(MetaMethod::Sub, |_, (lhs, rhs): (MyUserData, MyUserData)| {
|
||||
Ok(MyUserData(lhs.0 - rhs.0))
|
||||
});
|
||||
methods.add_meta_method(MetaMethod::Index, |lua, data, args| {
|
||||
let index = lua.unpack::<LuaString>(args)?;
|
||||
methods.add_meta_method(MetaMethod::Index, |_, data, index: LuaString| {
|
||||
if index.to_str()? == "inner" {
|
||||
lua.pack(data.0)
|
||||
Ok(data.0)
|
||||
} else {
|
||||
Err("no such custom index".to_lua_err())
|
||||
}
|
||||
|
@ -401,14 +395,10 @@ fn test_lua_multi() {
|
|||
let concat = globals.get::<_, Function>("concat").unwrap();
|
||||
let mreturn = globals.get::<_, Function>("mreturn").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
concat.call::<_, String>(hlist!["foo", "bar"]).unwrap(),
|
||||
"foobar"
|
||||
);
|
||||
let hlist_pat![a, b] = mreturn.call::<_, HList![u64, u64]>(hlist![]).unwrap();
|
||||
assert_eq!(concat.call::<_, String>(("foo", "bar")).unwrap(), "foobar");
|
||||
let (a, b) = mreturn.call::<_, (u64, u64)>(()).unwrap();
|
||||
assert_eq!((a, b), (1, 2));
|
||||
let hlist_pat![a, b, Variadic(v)] =
|
||||
mreturn.call::<_, HList![u64, u64, Variadic<u64>]>(hlist![]).unwrap();
|
||||
let (a, b, Variadic(v)) = mreturn.call::<_, (u64, u64, Variadic<u64>)>(()).unwrap();
|
||||
assert_eq!((a, b), (1, 2));
|
||||
assert_eq!(v, vec![3, 4, 5, 6]);
|
||||
}
|
||||
|
@ -507,7 +497,8 @@ fn test_error() {
|
|||
None,
|
||||
).unwrap();
|
||||
|
||||
let rust_error_function = lua.create_function(|_, _| Err(TestError.to_lua_err()));
|
||||
let rust_error_function =
|
||||
lua.create_function(|_, _: ()| -> Result<()> { Err(TestError.to_lua_err()) });
|
||||
globals
|
||||
.set("rust_error_function", rust_error_function)
|
||||
.unwrap();
|
||||
|
@ -566,7 +557,7 @@ fn test_error() {
|
|||
"#,
|
||||
None,
|
||||
)?;
|
||||
let rust_panic_function = lua.create_function(|_, _| {
|
||||
let rust_panic_function = lua.create_function(|_, _: ()| -> Result<()> {
|
||||
panic!("expected panic, this panic should be caught in rust")
|
||||
});
|
||||
globals.set("rust_panic_function", rust_panic_function)?;
|
||||
|
@ -592,7 +583,7 @@ fn test_error() {
|
|||
"#,
|
||||
None,
|
||||
)?;
|
||||
let rust_panic_function = lua.create_function(|_, _| {
|
||||
let rust_panic_function = lua.create_function(|_, _: ()| -> Result<()> {
|
||||
panic!("expected panic, this panic should be caught in rust")
|
||||
});
|
||||
globals.set("rust_panic_function", rust_panic_function)?;
|
||||
|
@ -749,12 +740,12 @@ fn test_result_conversions() {
|
|||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
|
||||
let err = lua.create_function(|lua, _| {
|
||||
lua.pack(Err::<String, _>(
|
||||
let err = lua.create_function(|_, _: ()| {
|
||||
Ok(Err::<String, _>(
|
||||
"only through failure can we succeed".to_lua_err(),
|
||||
))
|
||||
});
|
||||
let ok = lua.create_function(|lua, _| lua.pack(Ok::<_, Error>("!".to_owned())));
|
||||
let ok = lua.create_function(|_, _: ()| Ok(Ok::<_, Error>("!".to_owned())));
|
||||
|
||||
globals.set("err", err).unwrap();
|
||||
globals.set("ok", ok).unwrap();
|
||||
|
@ -806,9 +797,9 @@ fn test_expired_userdata() {
|
|||
|
||||
impl UserData for MyUserdata {
|
||||
fn add_methods(methods: &mut UserDataMethods<Self>) {
|
||||
methods.add_method("access", |lua, this, _| {
|
||||
methods.add_method("access", |_, this, _: ()| {
|
||||
assert!(this.id == 123);
|
||||
lua.pack(())
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -867,17 +858,26 @@ fn detroys_userdata() {
|
|||
#[test]
|
||||
fn string_views() {
|
||||
let lua = Lua::new();
|
||||
lua.eval::<()>(r#"
|
||||
lua.eval::<()>(
|
||||
r#"
|
||||
ok = "null bytes are valid utf-8, wh\0 knew?"
|
||||
err = "but \xff isn't :("
|
||||
"#, None).unwrap();
|
||||
"#,
|
||||
None,
|
||||
).unwrap();
|
||||
|
||||
let globals = lua.globals();
|
||||
let ok: LuaString = globals.get("ok").unwrap();
|
||||
let err: LuaString = globals.get("err").unwrap();
|
||||
|
||||
assert_eq!(ok.to_str().unwrap(), "null bytes are valid utf-8, wh\0 knew?");
|
||||
assert_eq!(ok.as_bytes(), &b"null bytes are valid utf-8, wh\0 knew?"[..]);
|
||||
assert_eq!(
|
||||
ok.to_str().unwrap(),
|
||||
"null bytes are valid utf-8, wh\0 knew?"
|
||||
);
|
||||
assert_eq!(
|
||||
ok.as_bytes(),
|
||||
&b"null bytes are valid utf-8, wh\0 knew?"[..]
|
||||
);
|
||||
|
||||
assert!(err.to_str().is_err());
|
||||
assert_eq!(err.as_bytes(), &b"but \xff isn't :("[..]);
|
||||
|
@ -886,9 +886,7 @@ fn string_views() {
|
|||
#[test]
|
||||
fn coroutine_from_closure() {
|
||||
let lua = Lua::new();
|
||||
let thrd_main = lua.create_function(|lua, _| {
|
||||
lua.pack(())
|
||||
});
|
||||
let thrd_main = lua.create_function(|_, _: ()| Ok(()));
|
||||
lua.globals().set("main", thrd_main).unwrap();
|
||||
let thrd: Thread = lua.eval("coroutine.create(main)", None).unwrap();
|
||||
thrd.resume::<_, ()>(()).unwrap();
|
||||
|
@ -898,10 +896,10 @@ fn coroutine_from_closure() {
|
|||
#[should_panic]
|
||||
fn coroutine_panic() {
|
||||
let lua = Lua::new();
|
||||
let thrd_main = lua.create_function(|lua, _| {
|
||||
let thrd_main = lua.create_function(|lua, _: ()| {
|
||||
// whoops, 'main' has a wrong type
|
||||
let _coro: u32 = lua.globals().get("main").unwrap();
|
||||
lua.pack(())
|
||||
Ok(())
|
||||
});
|
||||
lua.globals().set("main", thrd_main.clone()).unwrap();
|
||||
let thrd: Thread = lua.create_thread(thrd_main);
|
||||
|
|
Loading…
Reference in New Issue