Allow passing `Result<T, E>` to Lua

For this to work, both `T` and `E` need to implement `ToLua`. An `Ok(t)`
passes the contained `T`, while an `Err(e)` passes `nil` followed by the
contained `E`. This matches the common Lua idiom used by functions like
`io.open`.

Closes #3
This commit is contained in:
Jonas Schievink 2017-06-14 01:17:41 +02:00
parent 8440298e71
commit 80be9e8091
2 changed files with 45 additions and 0 deletions

View File

@ -15,6 +15,22 @@ impl<'lua> FromLuaMulti<'lua> for () {
}
}
impl<'lua, T: ToLua<'lua>, E: ToLua<'lua>> ToLuaMulti<'lua> for Result<T, E> {
fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> {
let mut result = LuaMultiValue::new();
match self {
Ok(v) => result.push_back(v.to_lua(lua)?),
Err(e) => {
result.push_back(LuaNil);
result.push_back(e.to_lua(lua)?);
}
}
Ok(result)
}
}
impl<'lua, T: ToLua<'lua>> ToLuaMulti<'lua> for T {
fn to_lua_multi(self, lua: &'lua Lua) -> LuaResult<LuaMultiValue<'lua>> {
let mut v = LuaMultiValue::new();

View File

@ -609,3 +609,32 @@ fn test_table_error() {
assert!(bad_table.pairs::<i64, i64>().is_ok());
assert!(bad_table.array_values::<i64>().is_ok());
}
#[test]
fn test_result_conversions() {
let lua = Lua::new();
let globals = lua.globals().unwrap();
let err = lua.create_function(|lua, args| {
lua.pack(Result::Err::<String, String>("only through failure can we succeed".to_string()))
}).unwrap();
let ok = lua.create_function(|lua, args| {
lua.pack(Result::Ok::<String, String>("!".to_string()))
}).unwrap();
globals.set("err", err).unwrap();
globals.set("ok", ok).unwrap();
lua.load::<()>(
r#"
local err, msg = err()
assert(err == nil)
assert(msg == "only through failure can we succeed")
local ok, extra = ok()
assert(ok == "!")
assert(extra == nil)
"#,
None,
).unwrap();
}