This is a SLIGHTLY better implementation I think.
This commit is contained in:
parent
2c439f8097
commit
cbae1a805a
|
@ -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<LuaValue<'lua>> {
|
||||
Ok(LuaValue::Error(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for LuaErrorUserData<'lua> {
|
||||
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<LuaErrorUserData<'lua>> {
|
||||
impl<'lua> FromLua<'lua> for LuaError {
|
||||
fn from_lua(value: LuaValue<'lua>, lua: &'lua Lua) -> LuaResult<LuaError> {
|
||||
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(|_| "<unprintable error>".to_owned()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for LuaError {
|
||||
fn to_lua(self, lua: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
|
||||
Ok(LuaValue::Error(lua.create_error(self)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> ToLua<'lua> for bool {
|
||||
fn to_lua(self, _: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
|
||||
Ok(LuaValue::Boolean(self))
|
||||
|
|
66
src/lua.rs
66
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<T: LuaUserDataType>(&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<LuaErrorUserData> {
|
||||
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<LuaTable> {
|
||||
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)))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue