diff --git a/src/conversion.rs b/src/conversion.rs index c7a5a45..426b817 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -117,29 +117,25 @@ impl<'lua, T: LuaUserDataType + Copy> FromLua<'lua> for T { } } -impl<'lua> ToLua<'lua> for LuaErrorUserData<'lua> { +impl<'lua> ToLua<'lua> for LuaError { fn to_lua(self, _: &'lua Lua) -> LuaResult> { Ok(LuaValue::Error(self)) } } -impl<'lua> FromLua<'lua> for LuaErrorUserData<'lua> { - fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult> { +impl<'lua> FromLua<'lua> for LuaError { + fn from_lua(value: LuaValue<'lua>, lua: &'lua Lua) -> LuaResult { match value { LuaValue::Error(err) => Ok(err), - _ => Err( - LuaConversionError::FromLua("cannot convert lua value to error".to_owned()).into(), - ), + val => Ok(LuaError::RuntimeError( + lua.coerce_string(val) + .and_then(|s| Ok(s.to_str()?.to_owned())) + .unwrap_or_else(|_| "".to_owned()), + )), } } } -impl<'lua> ToLua<'lua> for LuaError { - fn to_lua(self, lua: &'lua Lua) -> LuaResult> { - Ok(LuaValue::Error(lua.create_error(self)?)) - } -} - impl<'lua> ToLua<'lua> for bool { fn to_lua(self, _: &'lua Lua) -> LuaResult> { Ok(LuaValue::Boolean(self)) diff --git a/src/lua.rs b/src/lua.rs index 537a096..a382aab 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -44,8 +44,9 @@ pub enum LuaValue<'lua> { /// `LuaUserDataType`. Special builtin userdata types will be represented as /// other `LuaValue` variants. UserData(LuaUserData<'lua>), - /// `LuaError` is a special builtin userdata type. - Error(LuaErrorUserData<'lua>), + /// `LuaError` is a special builtin userdata type. When taken out of Lua it + /// is implicitly cloned. + Error(LuaError), } pub use self::LuaValue::Nil as LuaNil; @@ -226,11 +227,11 @@ impl<'lua> LuaTable<'lua> { let key = key.to_lua(lua)?; let value = value.to_lua(lua)?; unsafe { - error_guard(lua.state, 0, 0, |state| { - check_stack(state, 3)?; - lua.push_ref(state, &self.0); - lua.push_value(state, key); - lua.push_value(state, value); + check_stack(lua.state, 3)?; + lua.push_ref(lua.state, &self.0); + lua.push_value(lua.state, key); + lua.push_value(lua.state, value); + error_guard(lua.state, 3, 0, |state| { ffi::lua_settable(state, -3); Ok(()) }) @@ -247,10 +248,10 @@ impl<'lua> LuaTable<'lua> { let lua = self.0.lua; let key = key.to_lua(lua)?; unsafe { - let res = error_guard(lua.state, 0, 0, |state| { - check_stack(state, 2)?; - lua.push_ref(state, &self.0); - lua.push_value(state, key.to_lua(lua)?); + check_stack(lua.state, 2)?; + lua.push_ref(lua.state, &self.0); + lua.push_value(lua.state, key.to_lua(lua)?); + let res = error_guard(lua.state, 2, 0, |state| { ffi::lua_gettable(state, -2); let res = lua.pop_value(state); ffi::lua_pop(state, 1); @@ -265,10 +266,10 @@ impl<'lua> LuaTable<'lua> { let lua = self.0.lua; let key = key.to_lua(lua)?; unsafe { - error_guard(lua.state, 0, 0, |state| { - check_stack(state, 2)?; - lua.push_ref(state, &self.0); - lua.push_value(state, key); + check_stack(lua.state, 2)?; + lua.push_ref(lua.state, &self.0); + lua.push_value(lua.state, key); + error_guard(lua.state, 2, 0, |state| { ffi::lua_gettable(state, -2); let has = ffi::lua_isnil(state, -1) == 0; ffi::lua_pop(state, 2); @@ -955,27 +956,6 @@ impl<'lua> LuaUserData<'lua> { } } -/// Handle to a `LuaError` that is held internally in Lua -#[derive(Clone, Debug)] -pub struct LuaErrorUserData<'lua>(LuaRef<'lua>); - -impl<'lua> LuaErrorUserData<'lua> { - /// Gets a reference to the internally held `LuaError`. - pub fn get(&self) -> LuaResult<&LuaError> { - unsafe { - let lua = self.0.lua; - stack_guard(lua.state, 0, move || { - check_stack(lua.state, 1)?; - lua.push_ref(lua.state, &self.0); - - let userdata = ffi::lua_touserdata(lua.state, -1); - let err = &*(userdata as *const WrappedError); - Ok(&err.0) - }) - } - } -} - /// Top level Lua struct which holds the Lua state itself. pub struct Lua { state: *mut ffi::lua_State, @@ -1257,14 +1237,6 @@ impl Lua { } } - /// Create a userdata object from a LuaError - pub fn create_error(&self, err: LuaError) -> LuaResult { - unsafe { - push_wrapped_error(self.state, err); - Ok(LuaErrorUserData(self.pop_ref(self.state))) - } - } - /// Returns a handle to the global environment. pub fn globals(&self) -> LuaResult { unsafe { @@ -1474,7 +1446,7 @@ impl Lua { } LuaValue::Error(e) => { - self.push_ref(state, &e.0); + push_wrapped_error(state, e); } } } @@ -1521,8 +1493,8 @@ impl Lua { // other than custom LuaUserDataType types OR a WrappedError. // WrappedPanic should never be able to be caught in lua, so it // should never be here. - if is_wrapped_error(state, -1) { - LuaValue::Error(LuaErrorUserData(self.pop_ref(state))) + if let Some(err) = pop_wrapped_error(state) { + LuaValue::Error(err) } else { LuaValue::UserData(LuaUserData(self.pop_ref(state))) }