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:
kyren 2017-07-31 01:21:41 -04:00
parent 8ba3886c96
commit 4549abbb85
6 changed files with 190 additions and 154 deletions

View File

@ -20,6 +20,3 @@ builtin-lua = ["gcc"]
[build-dependencies]
gcc = { version = "0.3", optional = true }
[dependencies]
hlist-macro = "0.1"

View File

@ -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)?;

View File

@ -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;

View File

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

View File

@ -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 }

View File

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