summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkyren <kerriganw@gmail.com>2017-12-02 15:41:53 -0500
committerkyren <kerriganw@gmail.com>2017-12-02 15:41:53 -0500
commit8a7e03978bedc4403ef4f35fdf4c63a9fb5b862f (patch)
tree7758de8d84942a3f09f7767729cfcfc512061a50 /src
parentcfa2b34a7bbd91c31e6119962643d7e6e1e050d3 (diff)
downloadmlua-8a7e03978bedc4403ef4f35fdf4c63a9fb5b862f.zip
Experimental protected versions of all used 'm' erroring functions
Diffstat (limited to 'src')
-rw-r--r--src/ffi.rs3
-rw-r--r--src/lib.rs5
-rw-r--r--src/protected.rs258
-rw-r--r--src/table.rs1
-rw-r--r--src/util.rs105
5 files changed, 263 insertions, 109 deletions
diff --git a/src/ffi.rs b/src/ffi.rs
index 05ab3fa..9b03b58 100644
--- a/src/ffi.rs
+++ b/src/ffi.rs
@@ -1,7 +1,6 @@
-//! Bindings to the Lua 5.3 C API.
-
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
+#![allow(unused)]
use std::ptr;
use std::os::raw::{c_char, c_double, c_int, c_longlong, c_void};
diff --git a/src/lib.rs b/src/lib.rs
index 12542ad..b704fee 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -42,10 +42,11 @@
extern crate libc;
-pub mod ffi;
+mod ffi;
+mod error;
#[macro_use]
mod util;
-mod error;
+mod protected;
mod types;
mod lua;
mod conversion;
diff --git a/src/protected.rs b/src/protected.rs
new file mode 100644
index 0000000..d6d9065
--- /dev/null
+++ b/src/protected.rs
@@ -0,0 +1,258 @@
+use std::os::raw::{c_int, c_void, c_char};
+use std::{mem, ptr};
+
+use ffi;
+use error::{Result};
+use util::{handle_error, pcall_with_traceback};
+
+// Protected version of lua_gettable, uses 3 stack spaces, does not call checkstack.
+pub unsafe fn pgettable(state: *mut ffi::lua_State, index: c_int) -> Result<c_int> {
+ unsafe extern "C" fn gettable(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_gettable(state, -2);
+ 1
+ }
+
+ let table_index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, gettable);
+ ffi::lua_pushvalue(state, table_index);
+ ffi::lua_pushvalue(state, -3);
+ ffi::lua_remove(state, -4);
+
+ handle_error(state, pcall_with_traceback(state, 2, 1))?;
+ Ok(ffi::lua_type(state, -1))
+}
+
+// Protected version of lua_settable, uses 4 stack spaces, does not call checkstack.
+pub unsafe fn psettable(state: *mut ffi::lua_State, index: c_int) -> Result<()> {
+ unsafe extern "C" fn settable(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_settable(state, -3);
+ 0
+ }
+
+ let table_index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, settable);
+ ffi::lua_pushvalue(state, table_index);
+ ffi::lua_pushvalue(state, -4);
+ ffi::lua_pushvalue(state, -4);
+ ffi::lua_remove(state, -5);
+ ffi::lua_remove(state, -5);
+
+ handle_error(state, pcall_with_traceback(state, 3, 0))?;
+ Ok(())
+}
+
+// Protected version of luaL_len, uses 2 stack spaces, does not call checkstack.
+pub unsafe fn plen(state: *mut ffi::lua_State, index: c_int) -> Result<ffi::lua_Integer> {
+ unsafe extern "C" fn len(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_pushinteger(state, ffi::luaL_len(state, -1));
+ 1
+ }
+
+ let table_index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, len);
+ ffi::lua_pushvalue(state, table_index);
+
+ handle_error(state, pcall_with_traceback(state, 1, 1))?;
+ let len = ffi::lua_tointeger(state, -1);
+ ffi::lua_pop(state, 1);
+ Ok(len)
+}
+
+// Protected version of lua_geti, uses 3 stack spaces, does not call checkstack.
+pub unsafe fn pgeti(
+ state: *mut ffi::lua_State,
+ index: c_int,
+ i: ffi::lua_Integer,
+) -> Result<c_int> {
+ unsafe extern "C" fn geti(state: *mut ffi::lua_State) -> c_int {
+ let i = ffi::lua_tointeger(state, -1);
+ ffi::lua_geti(state, -2, i);
+ 1
+ }
+
+ let table_index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, geti);
+ ffi::lua_pushvalue(state, table_index);
+ ffi::lua_pushinteger(state, i);
+
+ handle_error(state, pcall_with_traceback(state, 2, 1))?;
+ Ok(ffi::lua_type(state, -1))
+}
+
+// Protected version of lua_next, uses 3 stack spaces, does not call checkstack.
+pub unsafe fn pnext(state: *mut ffi::lua_State, index: c_int) -> Result<c_int> {
+ unsafe extern "C" fn next(state: *mut ffi::lua_State) -> c_int {
+ if ffi::lua_next(state, -2) == 0 {
+ 0
+ } else {
+ 2
+ }
+ }
+
+ let table_index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, next);
+ ffi::lua_pushvalue(state, table_index);
+ ffi::lua_pushvalue(state, -3);
+ ffi::lua_remove(state, -4);
+
+ let stack_start = ffi::lua_gettop(state) - 3;
+ handle_error(state, pcall_with_traceback(state, 2, ffi::LUA_MULTRET))?;
+ let nresults = ffi::lua_gettop(state) - stack_start;
+ if nresults == 0 {
+ Ok(0)
+ } else {
+ Ok(1)
+ }
+}
+
+// Protected version of lua_newtable, uses 1 stack space, does not call checkstack.
+pub unsafe fn pnewtable(state: *mut ffi::lua_State) -> Result<()> {
+ unsafe extern "C" fn newtable(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_newtable(state);
+ 1
+ }
+
+ ffi::lua_pushcfunction(state, newtable);
+
+ handle_error(state, pcall_with_traceback(state, 0, 1))?;
+ Ok(())
+}
+
+// Protected version of lua_newthread, uses 1 stack space, does not call checkstack.
+pub unsafe fn pnewthread(state: *mut ffi::lua_State) -> Result<*mut ffi::lua_State> {
+ unsafe extern "C" fn newthread(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_newthread(state);
+ 1
+ }
+
+ ffi::lua_pushcfunction(state, newthread);
+
+ handle_error(state, pcall_with_traceback(state, 0, 1))?;
+ Ok(ffi::lua_tothread(state, -1))
+}
+
+// Protected version of lua_newuserdata, uses 2 stack space, does not call checkstack.
+pub unsafe fn pnewuserdata(state: *mut ffi::lua_State, size: usize) -> Result<*mut c_void> {
+ unsafe extern "C" fn newuserdata(state: *mut ffi::lua_State) -> c_int {
+ let size = ffi::lua_touserdata(state, -1) as usize;
+ ffi::lua_newuserdata(state, size);
+ 1
+ }
+
+ ffi::lua_pushcfunction(state, newuserdata);
+ ffi::lua_pushlightuserdata(state, size as *mut c_void);
+
+ handle_error(state, pcall_with_traceback(state, 1, 1))?;
+ Ok(ffi::lua_touserdata(state, -1))
+}
+
+pub unsafe fn ppushcclosure(state: *mut ffi::lua_State, function: ffi::lua_CFunction, n: c_int) -> Result<()> {
+ unsafe extern "C" fn pushcclosure(state: *mut ffi::lua_State) -> c_int {
+ let function: ffi::lua_CFunction = mem::transmute(ffi::lua_touserdata(state, -2));
+ let n = ffi::lua_touserdata(state, -1) as c_int;
+ ffi::lua_pop(state, 2);
+ ffi::lua_pushcclosure(state, function, n);
+ 1
+ }
+
+ if n == 0 {
+ ffi::lua_pushcclosure(state, function, 0);
+ } else {
+ ffi::lua_pushlightuserdata(state, function as *mut c_void);
+ ffi::lua_pushlightuserdata(state, n as *mut c_void);
+
+ handle_error(state, pcall_with_traceback(state, n.checked_add(2).unwrap(), 1))?;
+ }
+
+ Ok(())
+}
+
+pub unsafe fn ppushlstring(state: *mut ffi::lua_State, s: *const c_char, len: usize) -> Result<*const c_char> {
+ unsafe extern "C" fn pushlstring(state: *mut ffi::lua_State) -> c_int {
+ let s = ffi::lua_touserdata(state, -2) as *const c_char;
+ let len = ffi::lua_touserdata(state, -1) as usize;
+ ffi::lua_pushlstring(state, s, len);
+ 1
+ }
+
+ ffi::lua_pushlightuserdata(state, s as *mut c_void);
+ ffi::lua_pushlightuserdata(state, len as *mut c_void);
+
+ handle_error(state, pcall_with_traceback(state, 2, 1))?;
+
+ // If the value is already a string, I believe that lua_tostring / lua_tolstring never throw
+ // memory errors
+ Ok(ffi::lua_tostring(state, -1))
+}
+
+pub unsafe fn prawset(state: *mut ffi::lua_State, index: c_int) -> Result<()> {
+ unsafe extern "C" fn rawset(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_rawset(state, -3);
+ 0
+ }
+
+ let table_index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, rawset);
+ ffi::lua_pushvalue(state, table_index);
+ ffi::lua_pushvalue(state, -4);
+ ffi::lua_pushvalue(state, -4);
+ ffi::lua_remove(state, -5);
+ ffi::lua_remove(state, -5);
+
+ handle_error(state, pcall_with_traceback(state, 3, 0))?;
+ Ok(())
+}
+
+pub unsafe fn ptolstring(state: *mut ffi::lua_State, index: c_int, len: *mut usize) -> Result<*const c_char> {
+ unsafe extern "C" fn tolstring(state: *mut ffi::lua_State) -> c_int {
+ let len = ffi::lua_touserdata(state, -2) as *mut usize;
+ ffi::lua_tolstring(state, -1, len);
+ 1
+ }
+
+ let index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, tolstring);
+ ffi::lua_pushlightuserdata(state, len as *mut c_void);
+ ffi::lua_pushvalue(state, index);
+
+ match handle_error(state, pcall_with_traceback(state, 2, 1)) {
+ Ok(_) => {
+ ffi::lua_replace(state, index);
+ Ok(ffi::lua_tostring(state, index))
+ }
+ Err(err) => {
+ ffi::lua_pop(state, 1);
+ Err(err)
+ }
+ }
+}
+
+pub unsafe fn ptostring(state: *mut ffi::lua_State, index: c_int) -> Result<*const c_char> {
+ unsafe extern "C" fn tostring(state: *mut ffi::lua_State) -> c_int {
+ ffi::lua_tolstring(state, -1, ptr::null_mut());
+ 1
+ }
+
+ let index = ffi::lua_absindex(state, index);
+
+ ffi::lua_pushcfunction(state, tostring);
+ ffi::lua_pushvalue(state, index);
+
+ match handle_error(state, pcall_with_traceback(state, 1, 1)) {
+ Ok(_) => {
+ ffi::lua_replace(state, index);
+ Ok(ffi::lua_tostring(state, index))
+ }
+ Err(err) => {
+ ffi::lua_pop(state, 1);
+ Err(err)
+ }
+ }
+}
diff --git a/src/table.rs b/src/table.rs
index 6642171..a00dbc1 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -3,6 +3,7 @@ use std::marker::PhantomData;
use ffi;
use error::Result;
use util::*;
+use protected::*;
use types::{Integer, LuaRef};
use lua::{FromLua, ToLua};
diff --git a/src/util.rs b/src/util.rs
index 41c76fc..769024c 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -147,111 +147,6 @@ where
res
}
-// Protected version of lua_gettable, uses 3 stack spaces, does not call checkstack.
-pub unsafe fn pgettable(state: *mut ffi::lua_State, index: c_int) -> Result<c_int> {
- unsafe extern "C" fn gettable(state: *mut ffi::lua_State) -> c_int {
- ffi::lua_gettable(state, -2);
- 1
- }
-
- let table_index = ffi::lua_absindex(state, index);
-
- ffi::lua_pushcfunction(state, gettable);
- ffi::lua_pushvalue(state, table_index);
- ffi::lua_pushvalue(state, -3);
- ffi::lua_remove(state, -4);
-
- handle_error(state, pcall_with_traceback(state, 2, 1))?;
- Ok(ffi::lua_type(state, -1))
-}
-
-// Protected version of lua_settable, uses 4 stack spaces, does not call checkstack.
-pub unsafe fn psettable(state: *mut ffi::lua_State, index: c_int) -> Result<()> {
- unsafe extern "C" fn settable(state: *mut ffi::lua_State) -> c_int {
- ffi::lua_settable(state, -3);
- 0
- }
-
- let table_index = ffi::lua_absindex(state, index);
-
- ffi::lua_pushcfunction(state, settable);
- ffi::lua_pushvalue(state, table_index);
- ffi::lua_pushvalue(state, -4);
- ffi::lua_pushvalue(state, -4);
- ffi::lua_remove(state, -5);
- ffi::lua_remove(state, -5);
-
- handle_error(state, pcall_with_traceback(state, 3, 0))?;
- Ok(())
-}
-
-// Protected version of luaL_len, uses 2 stack spaces, does not call checkstack.
-pub unsafe fn plen(state: *mut ffi::lua_State, index: c_int) -> Result<ffi::lua_Integer> {
- unsafe extern "C" fn len(state: *mut ffi::lua_State) -> c_int {
- ffi::lua_pushinteger(state, ffi::luaL_len(state, -1));
- 1
- }
-
- let table_index = ffi::lua_absindex(state, index);
-
- ffi::lua_pushcfunction(state, len);
- ffi::lua_pushvalue(state, table_index);
-
- handle_error(state, pcall_with_traceback(state, 1, 1))?;
- let len = ffi::lua_tointeger(state, -1);
- ffi::lua_pop(state, 1);
- Ok(len)
-}
-
-// Protected version of lua_geti, uses 3 stack spaces, does not call checkstack.
-pub unsafe fn pgeti(
- state: *mut ffi::lua_State,
- index: c_int,
- i: ffi::lua_Integer,
-) -> Result<c_int> {
- unsafe extern "C" fn geti(state: *mut ffi::lua_State) -> c_int {
- let i = ffi::lua_tointeger(state, -1);
- ffi::lua_geti(state, -2, i);
- 1
- }
-
- let table_index = ffi::lua_absindex(state, index);
-
- ffi::lua_pushcfunction(state, geti);
- ffi::lua_pushvalue(state, table_index);
- ffi::lua_pushinteger(state, i);
-
- handle_error(state, pcall_with_traceback(state, 2, 1))?;
- Ok(ffi::lua_type(state, -1))
-}
-
-// Protected version of lua_next, uses 3 stack spaces, does not call checkstack.
-pub unsafe fn pnext(state: *mut ffi::lua_State, index: c_int) -> Result<c_int> {
- unsafe extern "C" fn next(state: *mut ffi::lua_State) -> c_int {
- if ffi::lua_next(state, -2) == 0 {
- 0
- } else {
- 2
- }
- }
-
- let table_index = ffi::lua_absindex(state, index);
-
- ffi::lua_pushcfunction(state, next);
- ffi::lua_pushvalue(state, table_index);
- ffi::lua_pushvalue(state, -3);
- ffi::lua_remove(state, -4);
-
- let stack_start = ffi::lua_gettop(state) - 3;
- handle_error(state, pcall_with_traceback(state, 2, ffi::LUA_MULTRET))?;
- let nresults = ffi::lua_gettop(state) - stack_start;
- if nresults == 0 {
- Ok(0)
- } else {
- Ok(1)
- }
-}
-
// If the return code indicates an error, pops the error off of the stack and
// returns Err. If the error is actually a WrappedPanic, clears the current lua
// stack and continues the panic. If the error on the top of the stack is