expose methods to operate on PushGuards from outside this library
This is most useful when using a library to poke at the Rust state. The most important methods made public are `new` to create a new `PushGuard`, and `forget` to not run this `PushGuard`'s destructor. They're both unsafe because their misuse can easily cause crashes. Also expose a `size` method to access the number of elements this `PushGuard` is managing, and provide an internal-only safe version of `forget` under the assumption that consumers within this crate know what they're doing.master
parent
42992f1448
commit
e8bcc05367
|
@ -64,7 +64,7 @@ impl<'lua, L> Push<L> for AnyLuaValue
|
|||
|
||||
// We also need to destroy and recreate the push guard, otherwise the type parameter
|
||||
// doesn't match.
|
||||
let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget();
|
||||
let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget_internal();
|
||||
|
||||
Ok(PushGuard {
|
||||
lua: lua,
|
||||
|
@ -149,7 +149,7 @@ impl<'lua, L> Push<L> for AnyHashableLuaValue
|
|||
|
||||
// We also need to destroy and recreate the push guard, otherwise the type parameter
|
||||
// doesn't match.
|
||||
let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget();
|
||||
let size = val.push_no_err(&mut lua as &mut AsMutLua<'lua>).forget_internal();
|
||||
|
||||
Ok(PushGuard {
|
||||
lua: lua,
|
||||
|
|
|
@ -69,7 +69,7 @@ impl_function!(function10, A, B, C, D, E, F, G, H, I, J);
|
|||
/// ```
|
||||
/// use hlua::Lua;
|
||||
/// let mut lua = Lua::new();
|
||||
///
|
||||
///
|
||||
/// lua.set("foo", hlua::function1(move |a: i32| -> i32 {
|
||||
/// a * 5
|
||||
/// }));
|
||||
|
@ -106,7 +106,7 @@ impl_function!(function10, A, B, C, D, E, F, G, H, I, J);
|
|||
/// ```
|
||||
/// use hlua::Lua;
|
||||
/// let mut lua = Lua::new();
|
||||
///
|
||||
///
|
||||
/// lua.set("values", hlua::function0(move || -> (i32, i32, i32) {
|
||||
/// (12, 24, 48)
|
||||
/// }));
|
||||
|
@ -130,7 +130,7 @@ impl_function!(function10, A, B, C, D, E, F, G, H, I, J);
|
|||
/// use hlua::Lua;
|
||||
/// let mut lua = Lua::new();
|
||||
/// lua.openlibs();
|
||||
///
|
||||
///
|
||||
/// lua.set("err", hlua::function0(move || -> Result<i32, &'static str> {
|
||||
/// Err("something wrong happened")
|
||||
/// }));
|
||||
|
@ -287,7 +287,7 @@ macro_rules! impl_function_ext {
|
|||
// without going through the RFC process.
|
||||
{
|
||||
match "__gc".push_to_lua(&mut lua) {
|
||||
Ok(p) => p.forget(),
|
||||
Ok(p) => p.forget_internal(),
|
||||
Err(_) => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -399,7 +399,7 @@ extern "C" fn wrapper<T, P, R>(lua: *mut ffi::lua_State) -> libc::c_int
|
|||
Err(_) => {
|
||||
let err_msg = format!("wrong parameter types for callback function");
|
||||
match err_msg.push_to_lua(&mut tmp_lua) {
|
||||
Ok(p) => p.forget(),
|
||||
Ok(p) => p.forget_internal(),
|
||||
Err(_) => unreachable!(),
|
||||
};
|
||||
unsafe {
|
||||
|
@ -414,7 +414,7 @@ extern "C" fn wrapper<T, P, R>(lua: *mut ffi::lua_State) -> libc::c_int
|
|||
|
||||
// pushing back the result of the function on the stack
|
||||
let nb = match ret_value.push_to_lua(&mut tmp_lua) {
|
||||
Ok(p) => p.forget(),
|
||||
Ok(p) => p.forget_internal(),
|
||||
Err(_) => panic!(), // TODO: wrong
|
||||
};
|
||||
nb as libc::c_int
|
||||
|
|
|
@ -170,16 +170,45 @@ pub struct PushGuard<L> {
|
|||
impl<'lua, L> PushGuard<L>
|
||||
where L: AsMutLua<'lua>
|
||||
{
|
||||
/// Creates a new `PushGuard` from this Lua context representing `size` items on the stack.
|
||||
/// When this `PushGuard` is destroyed, `size` items will be popped.
|
||||
///
|
||||
/// This is unsafe because the Lua stack can be corrupted if this is misused.
|
||||
#[inline]
|
||||
pub unsafe fn new(mut lua: L, size: i32) -> Self {
|
||||
let raw_lua = lua.as_mut_lua();
|
||||
PushGuard {
|
||||
lua,
|
||||
size,
|
||||
raw_lua,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_one_and_forget(self) -> i32 {
|
||||
assert_eq!(self.size, 1);
|
||||
self.forget()
|
||||
self.forget_internal()
|
||||
}
|
||||
|
||||
/// Prevents the value from being poped when the `PushGuard` is destroyed, and returns the
|
||||
/// number of elements on the stack.
|
||||
/// Returns the number of elements managed by this `PushGuard`.
|
||||
#[inline]
|
||||
fn forget(mut self) -> i32 {
|
||||
pub fn size(&self) -> i32 {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// Prevents the value from being popped when the `PushGuard` is destroyed, and returns the
|
||||
/// number of elements on the Lua stack.
|
||||
///
|
||||
/// This is unsafe because the Lua stack can be corrupted if this is misused.
|
||||
#[inline]
|
||||
pub unsafe fn forget(self) -> i32 {
|
||||
self.forget_internal()
|
||||
}
|
||||
|
||||
/// Internal crate-only version of `forget`. It is generally assumed that code within this
|
||||
/// crate that calls this method knows what it is doing.
|
||||
#[inline]
|
||||
fn forget_internal(mut self) -> i32 {
|
||||
let size = self.size;
|
||||
self.size = 0;
|
||||
size
|
||||
|
|
|
@ -264,7 +264,7 @@ impl<'lua, L> LuaFunction<L>
|
|||
// lua_pcall pops the function, so we have to make a copy of it
|
||||
ffi::lua_pushvalue(self.variable.as_mut_lua().0, -1);
|
||||
let num_pushed = match args.push_to_lua(self) {
|
||||
Ok(g) => g.forget(),
|
||||
Ok(g) => g.forget_internal(),
|
||||
Err((err, _)) => return Err(LuaFunctionCallError::PushError(err)),
|
||||
};
|
||||
let pcall_return_value = ffi::lua_pcall(self.variable.as_mut_lua().0, num_pushed, 1, 0); // TODO: num ret values
|
||||
|
|
|
@ -23,7 +23,7 @@ fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>,
|
|||
|
||||
for (elem, index) in iterator.zip((1..)) {
|
||||
let size = match elem.push_to_lua(&mut lua) {
|
||||
Ok(pushed) => pushed.forget(),
|
||||
Ok(pushed) => pushed.forget_internal(),
|
||||
Err((_err, _lua)) => panic!(), // TODO: wrong return Err((err, lua)), // FIXME: destroy the temporary table
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,7 @@ fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>,
|
|||
1 => {
|
||||
let index = index as u32;
|
||||
match index.push_to_lua(&mut lua) {
|
||||
Ok(pushed) => pushed.forget(),
|
||||
Ok(pushed) => pushed.forget_internal(),
|
||||
Err(_) => unreachable!(),
|
||||
};
|
||||
unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
|
||||
|
@ -64,7 +64,7 @@ fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<
|
|||
|
||||
for elem in iterator {
|
||||
let size = match elem.push_to_lua(&mut lua) {
|
||||
Ok(pushed) => pushed.forget(),
|
||||
Ok(pushed) => pushed.forget_internal(),
|
||||
Err((_err, _lua)) => panic!(), // TODO: wrong return Err((err, lua)), // FIXME: destroy the temporary table
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ macro_rules! tuple_impl {
|
|||
let mut total = 0;
|
||||
|
||||
let first_err = match $first.push_to_lua(&mut lua) {
|
||||
Ok(pushed) => { total += pushed.forget(); None },
|
||||
Ok(pushed) => { total += pushed.forget_internal(); None },
|
||||
Err((err, _)) => Some(err),
|
||||
};
|
||||
|
||||
|
@ -55,7 +55,7 @@ macro_rules! tuple_impl {
|
|||
|
||||
let rest = ($($other,)+);
|
||||
let other_err = match rest.push_to_lua(&mut lua) {
|
||||
Ok(pushed) => { total += pushed.forget(); None },
|
||||
Ok(pushed) => { total += pushed.forget_internal(); None },
|
||||
Err((err, _)) => Some(err),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue