diff options
author | kyren <kerriganw@gmail.com> | 2017-12-03 20:29:41 -0500 |
---|---|---|
committer | kyren <kerriganw@gmail.com> | 2017-12-03 20:29:41 -0500 |
commit | c95f591935edb4128dcd6be8d14cbb2f32b21413 (patch) | |
tree | 4496e01778279f7ec487adc9fe844b55d19cc52f | |
parent | 37a3145ced50077bf81e4076ba2a3b486af5ba6e (diff) | |
download | mlua-c95f591935edb4128dcd6be8d14cbb2f32b21413.zip |
remove specific protected functions in favor of generic protect_lua_call
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/protected_ffi.rs | 336 | ||||
-rw-r--r-- | src/table.rs | 53 | ||||
-rw-r--r-- | src/util.rs | 53 |
4 files changed, 31 insertions, 412 deletions
@@ -43,7 +43,6 @@ extern crate libc; mod ffi; -mod protected_ffi; mod error; #[macro_use] mod macros; diff --git a/src/protected_ffi.rs b/src/protected_ffi.rs deleted file mode 100644 index 9ddf691..0000000 --- a/src/protected_ffi.rs +++ /dev/null @@ -1,336 +0,0 @@ -#![allow(unused)] - -use std::os::raw::{c_char, c_int, c_void}; -use std::{mem, ptr}; - -use ffi; - -// 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, - msgh: c_int, -) -> Result<c_int, 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); - - let ret = ffi::lua_pcall(state, 2, 1, msgh); - if ret == ffi::LUA_OK { - Ok(ffi::lua_type(state, -1)) - } else { - Err(ret) - } -} - -// 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, - msgh: c_int, -) -> Result<(), c_int> { - 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); - - let ret = ffi::lua_pcall(state, 3, 0, msgh); - if ret == ffi::LUA_OK { - Ok(()) - } else { - Err(ret) - } -} - -// 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, - msgh: c_int, -) -> Result<ffi::lua_Integer, c_int> { - 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); - - let ret = ffi::lua_pcall(state, 1, 1, msgh); - if ret == ffi::LUA_OK { - let len = ffi::lua_tointeger(state, -1); - ffi::lua_pop(state, 1); - Ok(len) - } else { - Err(ret) - } -} - -// 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, - msgh: c_int, -) -> Result<c_int, 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); - - let ret = ffi::lua_pcall(state, 2, 1, msgh); - if ret == ffi::LUA_OK { - Ok(ffi::lua_type(state, -1)) - } else { - Err(ret) - } -} - -// 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, msgh: c_int) -> Result<c_int, 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; - let ret = ffi::lua_pcall(state, 2, ffi::LUA_MULTRET, msgh); - if ret == ffi::LUA_OK { - let nresults = ffi::lua_gettop(state) - stack_start; - if nresults == 0 { - Ok(0) - } else { - Ok(1) - } - } else { - Err(ret) - } -} - -// Protected version of lua_newtable, uses 1 stack space, does not call checkstack. -pub unsafe fn pnewtable(state: *mut ffi::lua_State, msgh: c_int) -> Result<(), c_int> { - unsafe extern "C" fn newtable(state: *mut ffi::lua_State) -> c_int { - ffi::lua_newtable(state); - 1 - } - - ffi::lua_pushcfunction(state, newtable); - - let ret = ffi::lua_pcall(state, 0, 1, msgh); - if ret == ffi::LUA_OK { - Ok(()) - } else { - Err(ret) - } -} - -// Protected version of lua_newthread, uses 1 stack space, does not call checkstack. -pub unsafe fn pnewthread( - state: *mut ffi::lua_State, - msgh: c_int, -) -> Result<*mut ffi::lua_State, c_int> { - unsafe extern "C" fn newthread(state: *mut ffi::lua_State) -> c_int { - ffi::lua_newthread(state); - 1 - } - - ffi::lua_pushcfunction(state, newthread); - - let ret = ffi::lua_pcall(state, 0, 1, msgh); - if ret == ffi::LUA_OK { - Ok(ffi::lua_tothread(state, -1)) - } else { - Err(ret) - } -} - -// Protected version of lua_newuserdata, uses 2 stack spaces, does not call checkstack. -pub unsafe fn pnewuserdata( - state: *mut ffi::lua_State, - size: usize, - msgh: c_int, -) -> Result<*mut c_void, c_int> { - 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); - - let ret = ffi::lua_pcall(state, 1, 1, msgh); - if ret == ffi::LUA_OK { - Ok(ffi::lua_touserdata(state, -1)) - } else { - Err(ret) - } -} - -// Protected version of lua_pushcclosure, uses 2 extra stack spaces, does not call checkstack. -pub unsafe fn ppushcclosure( - state: *mut ffi::lua_State, - function: ffi::lua_CFunction, - n: c_int, - msgh: c_int, -) -> Result<(), c_int> { - 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); - Ok(()) - } else { - ffi::lua_pushlightuserdata(state, function as *mut c_void); - ffi::lua_pushlightuserdata(state, n as *mut c_void); - - let ret = ffi::lua_pcall(state, n.checked_add(2).unwrap(), 1, msgh); - if ret == ffi::LUA_OK { - Ok(()) - } else { - Err(ret) - } - } -} - -pub unsafe fn ppushlstring( - state: *mut ffi::lua_State, - s: *const c_char, - len: usize, - msgh: c_int, -) -> Result<*const c_char, c_int> { - 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); - - let ret = ffi::lua_pcall(state, 2, 1, msgh); - if ret == ffi::LUA_OK { - // ffi::lua_tostring does not cause memory errors if the value is already a string - Ok(ffi::lua_tostring(state, -1)) - } else { - Err(ret) - } -} - -pub unsafe fn prawset(state: *mut ffi::lua_State, index: c_int, msgh: c_int) -> Result<(), c_int> { - 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); - - let ret = ffi::lua_pcall(state, 3, 0, msgh); - if ret == ffi::LUA_OK { - Ok(()) - } else { - Err(ret) - } -} - -pub unsafe fn ptolstring( - state: *mut ffi::lua_State, - index: c_int, - len: *mut usize, - msgh: c_int, -) -> Result<*const c_char, c_int> { - 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); - - let ret = ffi::lua_pcall(state, 2, 1, msgh); - if ret == ffi::LUA_OK { - ffi::lua_replace(state, index); - // ffi::lua_tostring does not cause memory errors if the value is already a string - Ok(ffi::lua_tostring(state, index)) - } else { - Err(ret) - } -} - -pub unsafe fn ptostring( - state: *mut ffi::lua_State, - index: c_int, - msgh: c_int, -) -> Result<*const c_char, c_int> { - 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); - - let ret = ffi::lua_pcall(state, 1, 1, msgh); - if ret == ffi::LUA_OK { - ffi::lua_replace(state, index); - // ffi::lua_tostring does not cause memory errors if the value is already a string - Ok(ffi::lua_tostring(state, index)) - } else { - Err(ret) - } -} diff --git a/src/table.rs b/src/table.rs index cfd83d1..7da679f 100644 --- a/src/table.rs +++ b/src/table.rs @@ -52,13 +52,13 @@ impl<'lua> Table<'lua> { let lua = self.0.lua; unsafe { stack_err_guard(lua.state, 0, || { - check_stack(lua.state, 8); + check_stack(lua.state, 6); lua.push_ref(lua.state, &self.0); lua.push_value(lua.state, key.to_lua(lua)?); lua.push_value(lua.state, value.to_lua(lua)?); - psettable(lua.state, -3)?; - ffi::lua_pop(lua.state, 1); - Ok(()) + protect_lua_call(lua.state, 3, 0, |state| { + ffi::lua_settable(state, -3); + }) }) } } @@ -95,13 +95,13 @@ impl<'lua> Table<'lua> { let lua = self.0.lua; unsafe { stack_err_guard(lua.state, 0, || { - check_stack(lua.state, 6); + check_stack(lua.state, 5); lua.push_ref(lua.state, &self.0); lua.push_value(lua.state, key.to_lua(lua)?); - pgettable(lua.state, -2)?; - let res = lua.pop_value(lua.state); - ffi::lua_pop(lua.state, 1); - V::from_lua(res, lua) + protect_lua_call(lua.state, 2, 1, |state| { + ffi::lua_gettable(state, -2) + })?; + V::from_lua(lua.pop_value(lua.state), lua) }) } } @@ -111,12 +111,14 @@ impl<'lua> Table<'lua> { let lua = self.0.lua; unsafe { stack_err_guard(lua.state, 0, || { - check_stack(lua.state, 6); + check_stack(lua.state, 5); lua.push_ref(lua.state, &self.0); lua.push_value(lua.state, key.to_lua(lua)?); - pgettable(lua.state, -2)?; + protect_lua_call(lua.state, 2, 1, |state| { + ffi::lua_gettable(state, -2) + })?; let has = ffi::lua_isnil(lua.state, -1) == 0; - ffi::lua_pop(lua.state, 2); + ffi::lua_pop(lua.state, 1); Ok(has) }) } @@ -163,11 +165,11 @@ impl<'lua> Table<'lua> { let lua = self.0.lua; unsafe { stack_err_guard(lua.state, 0, || { - check_stack(lua.state, 5); + check_stack(lua.state, 4); lua.push_ref(lua.state, &self.0); - let len = plen(lua.state, -1)?; - ffi::lua_pop(lua.state, 1); - Ok(len) + protect_lua_call(lua.state, 1, 0, |state| { + ffi::luaL_len(state, -1) + }) }) } } @@ -349,12 +351,18 @@ where unsafe { stack_guard(lua.state, 0, || { - check_stack(lua.state, 6); + check_stack(lua.state, 5); lua.push_ref(lua.state, &self.table); lua.push_ref(lua.state, &next_key); - match pnext(lua.state, -2) { + match protect_lua_call(lua.state, 2, ffi::LUA_MULTRET, |state| { + if ffi::lua_next(state, -2) == 0 { + 0 + } else { + 1 + } + }) { Ok(0) => { ffi::lua_pop(lua.state, 1); None @@ -405,17 +413,18 @@ where unsafe { stack_guard(lua.state, 0, || { - check_stack(lua.state, 5); + check_stack(lua.state, 4); lua.push_ref(lua.state, &self.table); - match pgeti(lua.state, -1, index) { + match protect_lua_call(lua.state, 1, 1, |state| { + ffi::lua_geti(state, -1, index) + }) { Ok(ffi::LUA_TNIL) => { - ffi::lua_pop(lua.state, 2); + ffi::lua_pop(lua.state, 1); None } Ok(_) => { let value = lua.pop_value(lua.state); - ffi::lua_pop(lua.state, 1); self.index = Some(index + 1); Some(V::from_lua(value, lua)) } diff --git a/src/util.rs b/src/util.rs index 6f07e74..bb3468b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -145,59 +145,6 @@ pub unsafe fn protect_lua_call<F, R>(state: *mut ffi::lua_State, nargs: c_int, n } } -// Protected version of lua_gettable, uses 4 stack spaces, does not call checkstack. -pub unsafe fn pgettable(state: *mut ffi::lua_State, index: c_int) -> Result<c_int> { - ffi::lua_pushvalue(state, index); - ffi::lua_insert(state, -2); - protect_lua_call(state, 2, 1, |state| { - ffi::lua_gettable(state, -2) - }) -} - -// Protected version of lua_settable, uses 5 stack spaces, does not call checkstack. -pub unsafe fn psettable(state: *mut ffi::lua_State, index: c_int) -> Result<()> { - ffi::lua_pushvalue(state, index); - ffi::lua_insert(state, -3); - protect_lua_call(state, 3, 0, |state| { - ffi::lua_settable(state, -3); - }) -} - -// Protected version of luaL_len, uses 4 stack spaces, does not call checkstack. -pub unsafe fn plen(state: *mut ffi::lua_State, index: c_int) -> Result<ffi::lua_Integer> { - ffi::lua_pushvalue(state, index); - protect_lua_call(state, 1, 0, |state| { - ffi::luaL_len(state, -1) - }) -} - -// Protected version of lua_geti, uses 4 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> { - ffi::lua_pushvalue(state, index); - protect_lua_call(state, 1, 1, |state| { - ffi::lua_geti(state, -1, i) - }) -} - -// Protected version of lua_next, uses 4 stack spaces, does not call checkstack. -pub unsafe fn pnext(state: *mut ffi::lua_State, index: c_int) -> Result<c_int> { - ffi::lua_pushvalue(state, index); - ffi::lua_insert(state, -2); - protect_lua_call(state, 2, ffi::LUA_MULTRET, |state| { - if ffi::lua_next(state, -2) == 0 { - ffi::lua_remove(state, -1); - 0 - } else { - ffi::lua_remove(state, -3); - 1 - } - }) -} - // Pops an error off of the stack and returns it. 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 actually // a WrappedError, just returns it. Otherwise, interprets the error as the appropriate lua error. |