summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkyren <kerriganw@gmail.com>2017-12-02 19:16:57 -0500
committerkyren <kerriganw@gmail.com>2017-12-02 19:16:57 -0500
commit5742e3f20ac025314d5e6365f4dde23526042608 (patch)
tree18e1d382f43d718afeb99839c622cd2da8f3fb16
parentf51a82273850c6e37510ea0dbc49ee279c9bf1ee (diff)
downloadmlua-5742e3f20ac025314d5e6365f4dde23526042608.zip
still making small structural changes
slowly trying to refactor things until using all the protected calls in protected_ffi is workable
-rw-r--r--src/util.rs109
1 files changed, 45 insertions, 64 deletions
diff --git a/src/util.rs b/src/util.rs
index 1d9b87e..5f2dc84 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -312,6 +312,36 @@ where
}
}
+// Takes an error at the top of the stack, and if it is a WrappedError, converts it to an
+// Error::CallbackError with a traceback. If it is a lua error, creates a new string error with a
+// printed traceback, and if it is a WrappedPanic, does not modify it.
+pub unsafe extern "C" fn error_traceback(state: *mut ffi::lua_State) -> c_int {
+ if let Some(error) = pop_wrapped_error(state) {
+ ffi::luaL_traceback(state, state, ptr::null(), 0);
+ let traceback = CStr::from_ptr(ffi::lua_tolstring(state, -1, ptr::null_mut()))
+ .to_string_lossy()
+ .into_owned();
+ push_wrapped_error(
+ state,
+ Error::CallbackError {
+ traceback,
+ cause: Arc::new(error),
+ },
+ );
+ ffi::lua_remove(state, -2);
+ } else if !is_wrapped_panic(state, 1) {
+ let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
+ let s = if s.is_null() {
+ cstr!("<unprintable Rust panic>")
+ } else {
+ s
+ };
+ ffi::luaL_traceback(state, state, s, 0);
+ ffi::lua_remove(state, -2);
+ }
+ 1
+}
+
// ffi::lua_pcall with a message handler that gives a nice traceback. If the
// caught error is actually a Error, will simply pass the error along. Does
// not call checkstack, and uses 2 extra stack spaces.
@@ -320,35 +350,8 @@ pub unsafe fn pcall_with_traceback(
nargs: c_int,
nresults: c_int,
) -> c_int {
- unsafe extern "C" fn message_handler(state: *mut ffi::lua_State) -> c_int {
- if let Some(error) = pop_wrapped_error(state) {
- ffi::luaL_traceback(state, state, ptr::null(), 0);
- let traceback = CStr::from_ptr(ffi::lua_tolstring(state, -1, ptr::null_mut()))
- .to_string_lossy()
- .into_owned();
- push_wrapped_error(
- state,
- Error::CallbackError {
- traceback,
- cause: Arc::new(error),
- },
- );
- ffi::lua_remove(state, -2);
- } else if !is_wrapped_panic(state, 1) {
- let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
- let s = if s.is_null() {
- cstr!("<unprintable Rust panic>")
- } else {
- s
- };
- ffi::luaL_traceback(state, state, s, 0);
- ffi::lua_remove(state, -2);
- }
- 1
- }
-
let msgh_position = ffi::lua_gettop(state) - nargs;
- ffi::lua_pushcfunction(state, message_handler);
+ ffi::lua_pushcfunction(state, error_traceback);
ffi::lua_insert(state, msgh_position);
let ret = ffi::lua_pcall(state, nargs, nresults, msgh_position);
ffi::lua_remove(state, msgh_position);
@@ -362,29 +365,7 @@ pub unsafe fn resume_with_traceback(
) -> c_int {
let res = ffi::lua_resume(state, from, nargs);
if res != ffi::LUA_OK && res != ffi::LUA_YIELD {
- if let Some(error) = pop_wrapped_error(state) {
- ffi::luaL_traceback(state, state, ptr::null(), 0);
- let traceback = CStr::from_ptr(ffi::lua_tolstring(state, -1, ptr::null_mut()))
- .to_str()
- .unwrap_or_else(|_| "<could not capture traceback>")
- .to_owned();
- push_wrapped_error(
- state,
- Error::CallbackError {
- traceback,
- cause: Arc::new(error),
- },
- );
- ffi::lua_remove(state, -2);
- } else if !is_wrapped_panic(state, 1) {
- let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
- if !s.is_null() {
- ffi::luaL_traceback(state, state, s, 0);
- } else {
- ffi::luaL_traceback(state, state, cstr!("<unprintable lua error>"), 0);
- }
- ffi::lua_remove(state, -2);
- }
+ error_traceback(state);
}
res
}
@@ -493,9 +474,6 @@ pub unsafe fn main_state(state: *mut ffi::lua_State) -> *mut ffi::lua_State {
main_state
}
-pub struct WrappedError(pub Error);
-pub struct WrappedPanic(pub Option<Box<Any + Send>>);
-
// Pushes a WrappedError::Error to the top of the stack
pub unsafe fn push_wrapped_error(state: *mut ffi::lua_State, err: Error) {
ffi::luaL_checkstack(state, 2, ptr::null());
@@ -506,16 +484,6 @@ pub unsafe fn push_wrapped_error(state: *mut ffi::lua_State, err: Error) {
ffi::lua_setmetatable(state, -2);
}
-// Pushes a WrappedError::Panic to the top of the stack
-pub unsafe fn push_wrapped_panic(state: *mut ffi::lua_State, panic: Box<Any + Send>) {
- ffi::luaL_checkstack(state, 2, ptr::null());
-
- push_userdata(state, WrappedPanic(Some(panic)));
-
- get_panic_metatable(state);
- ffi::lua_setmetatable(state, -2);
-}
-
// Pops a WrappedError off of the top of the stack, if it is a WrappedError. If
// it is not a WrappedError, returns None and does not pop anything.
pub unsafe fn pop_wrapped_error(state: *mut ffi::lua_State) -> Option<Error> {
@@ -529,6 +497,19 @@ pub unsafe fn pop_wrapped_error(state: *mut ffi::lua_State) -> Option<Error> {
}
}
+struct WrappedError(pub Error);
+struct WrappedPanic(pub Option<Box<Any + Send>>);
+
+// Pushes a WrappedError::Panic to the top of the stack
+unsafe fn push_wrapped_panic(state: *mut ffi::lua_State, panic: Box<Any + Send>) {
+ ffi::luaL_checkstack(state, 2, ptr::null());
+
+ push_userdata(state, WrappedPanic(Some(panic)));
+
+ get_panic_metatable(state);
+ ffi::lua_setmetatable(state, -2);
+}
+
// Checks if the value at the given index is a WrappedError
unsafe fn is_wrapped_error(state: *mut ffi::lua_State, index: c_int) -> bool {
assert_ne!(