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>> {
|
fn to_lua(self, _: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
|
||||||
Ok(LuaValue::Error(self))
|
Ok(LuaValue::Error(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'lua> FromLua<'lua> for LuaErrorUserData<'lua> {
|
impl<'lua> FromLua<'lua> for LuaError {
|
||||||
fn from_lua(value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<LuaErrorUserData<'lua>> {
|
fn from_lua(value: LuaValue<'lua>, lua: &'lua Lua) -> LuaResult<LuaError> {
|
||||||
match value {
|
match value {
|
||||||
LuaValue::Error(err) => Ok(err),
|
LuaValue::Error(err) => Ok(err),
|
||||||
_ => Err(
|
val => Ok(LuaError::RuntimeError(
|
||||||
LuaConversionError::FromLua("cannot convert lua value to error".to_owned()).into(),
|
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 {
|
impl<'lua> ToLua<'lua> for bool {
|
||||||
fn to_lua(self, _: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
|
fn to_lua(self, _: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
|
||||||
Ok(LuaValue::Boolean(self))
|
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
|
/// `LuaUserDataType`. Special builtin userdata types will be represented as
|
||||||
/// other `LuaValue` variants.
|
/// other `LuaValue` variants.
|
||||||
UserData(LuaUserData<'lua>),
|
UserData(LuaUserData<'lua>),
|
||||||
/// `LuaError` is a special builtin userdata type.
|
/// `LuaError` is a special builtin userdata type. When taken out of Lua it
|
||||||
Error(LuaErrorUserData<'lua>),
|
/// is implicitly cloned.
|
||||||
|
Error(LuaError),
|
||||||
}
|
}
|
||||||
pub use self::LuaValue::Nil as LuaNil;
|
pub use self::LuaValue::Nil as LuaNil;
|
||||||
|
|
||||||
|
@ -226,11 +227,11 @@ impl<'lua> LuaTable<'lua> {
|
||||||
let key = key.to_lua(lua)?;
|
let key = key.to_lua(lua)?;
|
||||||
let value = value.to_lua(lua)?;
|
let value = value.to_lua(lua)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
error_guard(lua.state, 0, 0, |state| {
|
check_stack(lua.state, 3)?;
|
||||||
check_stack(state, 3)?;
|
lua.push_ref(lua.state, &self.0);
|
||||||
lua.push_ref(state, &self.0);
|
lua.push_value(lua.state, key);
|
||||||
lua.push_value(state, key);
|
lua.push_value(lua.state, value);
|
||||||
lua.push_value(state, value);
|
error_guard(lua.state, 3, 0, |state| {
|
||||||
ffi::lua_settable(state, -3);
|
ffi::lua_settable(state, -3);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -247,10 +248,10 @@ impl<'lua> LuaTable<'lua> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
let key = key.to_lua(lua)?;
|
let key = key.to_lua(lua)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let res = error_guard(lua.state, 0, 0, |state| {
|
check_stack(lua.state, 2)?;
|
||||||
check_stack(state, 2)?;
|
lua.push_ref(lua.state, &self.0);
|
||||||
lua.push_ref(state, &self.0);
|
lua.push_value(lua.state, key.to_lua(lua)?);
|
||||||
lua.push_value(state, key.to_lua(lua)?);
|
let res = error_guard(lua.state, 2, 0, |state| {
|
||||||
ffi::lua_gettable(state, -2);
|
ffi::lua_gettable(state, -2);
|
||||||
let res = lua.pop_value(state);
|
let res = lua.pop_value(state);
|
||||||
ffi::lua_pop(state, 1);
|
ffi::lua_pop(state, 1);
|
||||||
|
@ -265,10 +266,10 @@ impl<'lua> LuaTable<'lua> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
let key = key.to_lua(lua)?;
|
let key = key.to_lua(lua)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
error_guard(lua.state, 0, 0, |state| {
|
check_stack(lua.state, 2)?;
|
||||||
check_stack(state, 2)?;
|
lua.push_ref(lua.state, &self.0);
|
||||||
lua.push_ref(state, &self.0);
|
lua.push_value(lua.state, key);
|
||||||
lua.push_value(state, key);
|
error_guard(lua.state, 2, 0, |state| {
|
||||||
ffi::lua_gettable(state, -2);
|
ffi::lua_gettable(state, -2);
|
||||||
let has = ffi::lua_isnil(state, -1) == 0;
|
let has = ffi::lua_isnil(state, -1) == 0;
|
||||||
ffi::lua_pop(state, 2);
|
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.
|
/// Top level Lua struct which holds the Lua state itself.
|
||||||
pub struct Lua {
|
pub struct Lua {
|
||||||
state: *mut ffi::lua_State,
|
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.
|
/// Returns a handle to the global environment.
|
||||||
pub fn globals(&self) -> LuaResult<LuaTable> {
|
pub fn globals(&self) -> LuaResult<LuaTable> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1474,7 +1446,7 @@ impl Lua {
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaValue::Error(e) => {
|
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.
|
// other than custom LuaUserDataType types OR a WrappedError.
|
||||||
// WrappedPanic should never be able to be caught in lua, so it
|
// WrappedPanic should never be able to be caught in lua, so it
|
||||||
// should never be here.
|
// should never be here.
|
||||||
if is_wrapped_error(state, -1) {
|
if let Some(err) = pop_wrapped_error(state) {
|
||||||
LuaValue::Error(LuaErrorUserData(self.pop_ref(state)))
|
LuaValue::Error(err)
|
||||||
} else {
|
} else {
|
||||||
LuaValue::UserData(LuaUserData(self.pop_ref(state)))
|
LuaValue::UserData(LuaUserData(self.pop_ref(state)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue