aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src/program/hook.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-15 03:28:02 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-15 03:28:02 +0800
commitec6c87d12062576271231b88364a4aa00765ae65 (patch)
treec1fcc3583aaffa06c0857403b557231719dde1af /mingling_core/src/program/hook.rs
parent372eb14ab9a9b7fc0e5334ca15a9d8b656140e54 (diff)
feat(core): allow pre_dispatch hooks to mutate arguments
Change `HookPreDispatchInfo.arguments` from `&[String]` to `&mut Vec<String>` so hooks can rewrite command-line arguments before dispatch.
Diffstat (limited to 'mingling_core/src/program/hook.rs')
-rw-r--r--mingling_core/src/program/hook.rs31
1 files changed, 20 insertions, 11 deletions
diff --git a/mingling_core/src/program/hook.rs b/mingling_core/src/program/hook.rs
index 8fd2ba1..92106f9 100644
--- a/mingling_core/src/program/hook.rs
+++ b/mingling_core/src/program/hook.rs
@@ -64,8 +64,9 @@ where
pub begin: Option<Box<dyn Fn(&HookBeginInfo) + Send + Sync>>,
/// Executes before the program dispatches
- pub pre_dispatch:
- Option<Box<dyn for<'a> Fn(&HookPreDispatchInfo<'a>) -> ProgramControls<C> + Send + Sync>>,
+ pub pre_dispatch: Option<
+ Box<dyn for<'a> Fn(&mut HookPreDispatchInfo<'a>) -> ProgramControls<C> + Send + Sync>,
+ >,
/// Executes after the program dispatches
pub post_dispatch: Option<
@@ -162,7 +163,10 @@ where
}
}
- pub(crate) fn run_hook_pre_dispatch(&self, info: &HookPreDispatchInfo) -> ProgramControls<C> {
+ pub(crate) fn run_hook_pre_dispatch(
+ &self,
+ info: &mut HookPreDispatchInfo,
+ ) -> ProgramControls<C> {
if !self.user_context.run_hook {
return ProgramControls::Empty;
}
@@ -475,7 +479,7 @@ where
#[must_use]
pub fn on_pre_dispatch<F, R>(mut self, handler: F) -> Self
where
- F: for<'a> Fn(&HookPreDispatchInfo<'a>) -> R + 'static + Send + Sync,
+ F: for<'a> Fn(&mut HookPreDispatchInfo<'a>) -> R + 'static + Send + Sync,
R: Into<ProgramControls<C>>,
{
self.pre_dispatch = Some(Box::new(move |info| handler(info).into()));
@@ -801,16 +805,21 @@ mod tests {
#[test]
fn test_hook_on_pre_dispatch() {
static CALLED: AtomicBool = AtomicBool::new(false);
- let hook =
- ProgramHook::<MockHookEnum>::empty().on_pre_dispatch(|info: &HookPreDispatchInfo| {
- assert_eq!(info.arguments, &["a", "b"]);
+ let mut args = vec!["a".to_string(), "b".to_string()];
+ let hook = ProgramHook::<MockHookEnum>::empty().on_pre_dispatch(
+ |info: &mut HookPreDispatchInfo| {
+ assert_eq!(info.arguments.as_slice(), &["a", "b"]);
+ // The hook may rewrite the arguments before dispatch
+ info.arguments.push("c".to_string());
CALLED.store(true, Ordering::SeqCst);
- });
+ },
+ );
assert!(hook.pre_dispatch.is_some());
- (hook.pre_dispatch.as_ref().unwrap())(&HookPreDispatchInfo {
- arguments: &["a".to_string(), "b".to_string()],
+ (hook.pre_dispatch.as_ref().unwrap())(&mut HookPreDispatchInfo {
+ arguments: &mut args,
});
assert!(CALLED.load(Ordering::SeqCst));
+ assert_eq!(args.as_slice(), &["a", "b", "c"]);
}
#[test]
@@ -910,7 +919,7 @@ mod tests {
fn test_hook_builder_chaining() {
let hook = ProgramHook::<MockHookEnum>::empty()
.on_begin::<_, ()>(|_: &HookBeginInfo| ())
- .on_pre_dispatch(|_: &HookPreDispatchInfo| ())
+ .on_pre_dispatch(|_: &mut HookPreDispatchInfo| ())
.on_post_dispatch(|_: &HookPostDispatchInfo<MockHookEnum>| ())
.on_pre_chain(|_: &HookPreChainInfo<MockHookEnum>| ())
.on_post_chain(|_: &HookPostChainInfo<MockHookEnum>| ())