From 4acec5adf2a224a8220eecd6da70eba0dfbb97a4 Mon Sep 17 00:00:00 2001 From: William Venner Date: Wed, 6 Oct 2021 18:24:12 +0100 Subject: [PATCH] Add `lua_stack_guard` macro --- Cargo.lock | 2 +- gmod/Cargo.toml | 2 +- gmod/src/lua/mod.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c532426..3c706e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,7 +109,7 @@ dependencies = [ [[package]] name = "gmod" -version = "4.0.1" +version = "4.0.2" dependencies = [ "cfg_table", "cstr", diff --git a/gmod/Cargo.toml b/gmod/Cargo.toml index bfcc76e..913f80d 100644 --- a/gmod/Cargo.toml +++ b/gmod/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gmod" -version = "4.0.1" +version = "4.0.2" authors = ["William Venner "] edition = "2018" license = "MIT" diff --git a/gmod/src/lua/mod.rs b/gmod/src/lua/mod.rs index 77cc56d..b048236 100644 --- a/gmod/src/lua/mod.rs +++ b/gmod/src/lua/mod.rs @@ -44,3 +44,37 @@ macro_rules! lua_string { $crate::cstr::cstr!($str).as_ptr() }; } + +/// Enforces a debug assertion that the Lua stack is unchanged after this block of code is executed. +/// +/// Useful for ensuring stack hygiene. +/// +/// `lua` is the Lua state to check. +/// +/// # Example +/// +/// ```rust,norun +/// lua_stack_guard!(lua => { +/// lua.get_global(lua_string!("hook")); +/// lua.get_field(-1, lua_string!("Add")); +/// lua.push_string("PlayerInitialSpawn"); +/// lua.push_string("RustHook"); +/// lua.push_function(player_initial_spawn); +/// lua.call(3, 0); +/// // lua.pop(); +/// }); +/// // PANIC: stack is dirty! We forgot to pop the hook library off the stack. +/// ``` +#[macro_export] +macro_rules! lua_stack_guard { + ( $lua:ident => $code:block ) => {{ + #[cfg(debug_assertions)] { + let top = $lua.get_top(); + $code + assert_eq!(top, $lua.get_top(), "Stack is dirty!"); + } + + #[cfg(not(debug_assertions))] + $code + }}; +} \ No newline at end of file