diff --git a/src/hook.rs b/src/hook.rs index c0fd762..de4e366 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -266,48 +266,59 @@ pub struct HookTriggers { #[cfg(not(feature = "luau"))] impl HookTriggers { - /// Returns a new instance of `HookTriggers` with [`on_calls`] trigger set. + /// An instance of `HookTriggers` with `on_calls` trigger set. + pub const ON_CALLS: Self = HookTriggers::new().on_calls(); + + /// An instance of `HookTriggers` with `on_returns` trigger set. + pub const ON_RETURNS: Self = HookTriggers::new().on_returns(); + + /// An instance of `HookTriggers` with `every_line` trigger set. + pub const EVERY_LINE: Self = HookTriggers::new().every_line(); + + /// Returns a new instance of `HookTriggers` with all triggers disabled. + pub const fn new() -> Self { + HookTriggers { + on_calls: false, + on_returns: false, + every_line: false, + every_nth_instruction: None, + } + } + + /// Returns an instance of `HookTriggers` with [`on_calls`] trigger set. /// /// [`on_calls`]: #structfield.on_calls - pub fn on_calls() -> Self { - HookTriggers { - on_calls: true, - ..Default::default() - } + pub const fn on_calls(mut self) -> Self { + self.on_calls = true; + self } - /// Returns a new instance of `HookTriggers` with [`on_returns`] trigger set. + /// Returns an instance of `HookTriggers` with [`on_returns`] trigger set. /// /// [`on_returns`]: #structfield.on_returns - pub fn on_returns() -> Self { - HookTriggers { - on_returns: true, - ..Default::default() - } + pub const fn on_returns(mut self) -> Self { + self.on_returns = true; + self } - /// Returns a new instance of `HookTriggers` with [`every_line`] trigger set. + /// Returns an instance of `HookTriggers` with [`every_line`] trigger set. /// /// [`every_line`]: #structfield.every_line - pub fn every_line() -> Self { - HookTriggers { - every_line: true, - ..Default::default() - } + pub const fn every_line(mut self) -> Self { + self.every_line = true; + self } - /// Returns a new instance of `HookTriggers` with [`every_nth_instruction`] trigger set. + /// Returns an instance of `HookTriggers` with [`every_nth_instruction`] trigger set. /// /// [`every_nth_instruction`]: #structfield.every_nth_instruction - pub fn every_nth_instruction(n: u32) -> Self { - HookTriggers { - every_nth_instruction: Some(n), - ..Default::default() - } + pub const fn every_nth_instruction(mut self, n: u32) -> Self { + self.every_nth_instruction = Some(n); + self } // Compute the mask to pass to `lua_sethook`. - pub(crate) fn mask(&self) -> c_int { + pub(crate) const fn mask(&self) -> c_int { let mut mask: c_int = 0; if self.on_calls { mask |= ffi::LUA_MASKCALL @@ -326,8 +337,9 @@ impl HookTriggers { // Returns the `count` parameter to pass to `lua_sethook`, if applicable. Otherwise, zero is // returned. - pub(crate) fn count(&self) -> c_int { - self.every_nth_instruction.unwrap_or(0) as c_int + pub(crate) const fn count(&self) -> c_int { + let Some(n) = self.every_nth_instruction else { return 0 }; + n as c_int } } diff --git a/tests/hooks.rs b/tests/hooks.rs index 2fbd33d..2549f10 100644 --- a/tests/hooks.rs +++ b/tests/hooks.rs @@ -10,10 +10,11 @@ use mlua::{DebugEvent, Error, HookTriggers, Lua, Result, Value}; #[test] fn test_hook_triggers_bitor() { - let trigger = HookTriggers::on_calls() - | HookTriggers::on_returns() - | HookTriggers::every_line() - | HookTriggers::every_nth_instruction(5); + let trigger = HookTriggers::new() + .on_calls() + .on_returns() + .every_line() + .every_nth_instruction(5); assert!(trigger.on_calls); assert!(trigger.on_returns); @@ -27,7 +28,7 @@ fn test_line_counts() -> Result<()> { let hook_output = output.clone(); let lua = Lua::new(); - lua.set_hook(HookTriggers::every_line(), move |_lua, debug| { + lua.set_hook(HookTriggers::EVERY_LINE, move |_lua, debug| { assert_eq!(debug.event(), DebugEvent::Line); hook_output.lock().unwrap().push(debug.curr_line()); Ok(()) @@ -59,7 +60,7 @@ fn test_function_calls() -> Result<()> { let hook_output = output.clone(); let lua = Lua::new(); - lua.set_hook(HookTriggers::on_calls(), move |_lua, debug| { + lua.set_hook(HookTriggers::ON_CALLS, move |_lua, debug| { assert_eq!(debug.event(), DebugEvent::Call); let names = debug.names(); let source = debug.source(); @@ -104,7 +105,7 @@ fn test_function_calls() -> Result<()> { fn test_error_within_hook() -> Result<()> { let lua = Lua::new(); - lua.set_hook(HookTriggers::every_line(), |_lua, _debug| { + lua.set_hook(HookTriggers::EVERY_LINE, |_lua, _debug| { Err(Error::RuntimeError( "Something happened in there!".to_string(), )) @@ -136,7 +137,7 @@ fn test_limit_execution_instructions() -> Result<()> { let max_instructions = AtomicI64::new(10000); lua.set_hook( - HookTriggers::every_nth_instruction(30), + HookTriggers::new().every_nth_instruction(30), move |_lua, debug| { assert_eq!(debug.event(), DebugEvent::Count); if max_instructions.fetch_sub(30, Ordering::Relaxed) <= 30 { @@ -166,11 +167,14 @@ fn test_limit_execution_instructions() -> Result<()> { fn test_hook_removal() -> Result<()> { let lua = Lua::new(); - lua.set_hook(HookTriggers::every_nth_instruction(1), |_lua, _debug| { - Err(Error::RuntimeError( - "this hook should've been removed by this time".to_string(), - )) - })?; + lua.set_hook( + HookTriggers::new().every_nth_instruction(1), + |_lua, _debug| { + Err(Error::RuntimeError( + "this hook should've been removed by this time".to_string(), + )) + }, + )?; assert!(lua.load("local x = 1").exec().is_err()); lua.remove_hook(); @@ -193,11 +197,11 @@ fn test_hook_swap_within_hook() -> Result<()> { tl.borrow() .as_ref() .unwrap() - .set_hook(HookTriggers::every_line(), move |lua, _debug| { + .set_hook(HookTriggers::EVERY_LINE, move |lua, _debug| { lua.globals().set("ok", 1i64)?; TL_LUA.with(|tl| { tl.borrow().as_ref().unwrap().set_hook( - HookTriggers::every_line(), + HookTriggers::EVERY_LINE, move |lua, _debug| { lua.load( r#"