From 1d1baf75a3acb5eb32913a8bdad42bae42844aa2 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 24 Jun 2026 12:01:38 +0800 Subject: Redesign hook system with structured info types and ProgramControls --- mingling_core/src/program/hook/control_unit.rs | 140 +++++++++++++++++++++++++ mingling_core/src/program/hook/hook_info.rs | 119 +++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 mingling_core/src/program/hook/control_unit.rs (limited to 'mingling_core/src/program/hook') diff --git a/mingling_core/src/program/hook/control_unit.rs b/mingling_core/src/program/hook/control_unit.rs new file mode 100644 index 0000000..b35cf3d --- /dev/null +++ b/mingling_core/src/program/hook/control_unit.rs @@ -0,0 +1,140 @@ +use crate::{AnyOutput, ProgramCollect}; + +/// Collection variants for program control instructions. +/// +/// Defines different forms of program control collections. +pub enum ProgramControls +where + C: ProgramCollect, +{ + /// Empty collection. + Empty, + + /// A single control unit. + Single(ProgramControlUnit), + + /// A collection of multiple control units. + Multi(Vec>), +} + +impl ProgramControls +where + C: ProgramCollect, +{ + /// Returns `true` if the collection is empty. + pub fn is_empty(&self) -> bool { + matches!(self, ProgramControls::Empty) + } +} + +impl From<()> for ProgramControls +where + C: ProgramCollect, +{ + fn from(_: ()) -> Self { + Self::Empty + } +} + +impl From> for ProgramControls +where + C: ProgramCollect, +{ + fn from(unit: ProgramControlUnit) -> Self { + Self::Single(unit) + } +} + +impl From>> for ProgramControls +where + C: ProgramCollect, +{ + fn from(units: Vec>) -> Self { + Self::Multi(units) + } +} + +impl IntoIterator for ProgramControls +where + C: ProgramCollect, +{ + type Item = ProgramControlUnit; + type IntoIter = ProgramControlsIter; + + fn into_iter(self) -> Self::IntoIter { + match self { + ProgramControls::Empty => ProgramControlsIter { + inner: vec![].into_iter(), + }, + ProgramControls::Single(unit) => ProgramControlsIter { + inner: vec![unit].into_iter(), + }, + ProgramControls::Multi(units) => ProgramControlsIter { + inner: units.into_iter(), + }, + } + } +} + +/// An iterator over [`ProgramControlUnit`] values. +pub struct ProgramControlsIter +where + C: ProgramCollect, +{ + inner: std::vec::IntoIter>, +} + +impl Iterator for ProgramControlsIter +where + C: ProgramCollect, +{ + type Item = ProgramControlUnit; + + fn next(&mut self) -> Option { + self.inner.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +impl std::iter::FusedIterator for ProgramControlsIter +where + C: ProgramCollect, +{ + // Auto impl +} + +/// Enumeration of program control units. +/// +/// Defines the various control flow instructions that a program may encounter during execution, +/// used to alter the default execution flow (e.g., interruption, jump, or redirection). +pub enum ProgramControlUnit +where + C: ProgramCollect, +{ + /// Override the program exit code. + /// + /// Used when a non-default process exit code needs to be forcibly specified. + /// The contained `i32` value is the exit code to be set. + OverrideExitCode(i32), + + /// Route to the render flow. + /// + /// Transfers control to the rendering (output) stage, + /// carrying the `AnyOutput` to be rendered. + RouteToRender(AnyOutput), + + /// Route to the chain processing flow. + /// + /// Transfers control to the next chained processor, + /// carrying the `AnyOutput` that needs to be passed along. + RouteToChain(AnyOutput), + + /// Route to the help information flow. + /// + /// Transfers control to the help information display module, + /// carrying the `AnyOutput` containing help-related content. + RouteToHelp(AnyOutput), +} diff --git a/mingling_core/src/program/hook/hook_info.rs b/mingling_core/src/program/hook/hook_info.rs index e69de29..060e368 100644 --- a/mingling_core/src/program/hook/hook_info.rs +++ b/mingling_core/src/program/hook/hook_info.rs @@ -0,0 +1,119 @@ +use crate::{AnyOutput, ProgramCollect, RenderResult}; + +/// Represents the data passed to `begin` hook. +pub struct HookBeginInfo {} + +/// Represents the data passed to `pre_dispatch` hook. +pub struct HookPreDispatchInfo<'a> { + /// Arguments entered by the user before dispatching + pub arguments: &'a [String], +} + +/// Represents the data passed to `post_dispatch` hook. +pub struct HookPostDispatchInfo<'a, C> +where + C: ProgramCollect, +{ + /// The entry point of dispatching + pub entry: &'a C, +} + +/// Represents the data passed to `pre_chain` hook. +pub struct HookPreChainInfo<'a, C> +where + C: ProgramCollect, +{ + /// Input to the chain + pub input: &'a C, + + /// Raw data + pub raw: &'a dyn std::any::Any, +} + +/// Represents the data passed to `post_chain` hook. +pub struct HookPostChainInfo<'a, C> +where + C: ProgramCollect, +{ + /// Output of the chain + pub output: &'a AnyOutput, +} + +/// Represents the data passed to `pre_render` hook. +pub struct HookPreRenderInfo<'a, C> +where + C: ProgramCollect, +{ + /// Render input + pub input: &'a C, + + /// The raw data to be rendered + pub raw: &'a dyn std::any::Any, +} + +/// Represents the data passed to `post_render` hook. +pub struct HookPostRenderInfo<'a> { + /// The rendering result + pub result: &'a RenderResult, +} + +/// Represents the data passed to `finish` hook. +pub struct HookFinishInfo {} + +/// Represents the data passed to `exec_panic` hook. +#[cfg(not(feature = "async"))] +pub struct HookPanicInfo<'a> { + /// Raw data of the panic + pub panic: &'a crate::error::ProgramPanic, +} + +#[cfg(feature = "repl")] +mod repl_hook { + use crate::RenderResult; + + /// Represents the data passed to `repl_on_begin` hook. + pub struct HookREPLBeginInfo {} + + /// Represents the data passed to `repl_pre_readline` hook. + pub struct HookREPLPreReadlineInfo {} + + /// Represents the data passed to `repl_readline` hook. + pub struct HookREPLReadlineInfo {} + + /// Represents the data passed to `repl_post_readline` hook. + pub struct HookREPLPostReadlineInfo<'a> { + /// The read line (mutable for editing) + pub line: &'a mut String, + } + + /// Represents the data passed to `repl_pre_exec` hook. + pub struct HookREPLPreExecInfo<'a> { + /// Arguments for the command + pub args: &'a [String], + } + + /// Represents the data passed to `repl_post_exec` hook. + pub struct HookREPLPostExecInfo {} + + /// Represents the data passed to `repl_on_receive_result` hook. + pub struct HookREPLOnReceiveResultInfo<'a> { + /// The rendering result + pub result: &'a RenderResult, + } + + /// Represents the data passed to `repl_exit` hook. + pub struct HookREPLExitInfo {} + + /// Represents the data passed to `repl_loop_once` hook. + pub struct HookREPLLoopOnceInfo {} + + /// Represents the data passed to `repl_on_panic` hook. + #[cfg(not(feature = "async"))] + pub struct HookREPLOnPanicInfo<'a> { + /// Raw data of the panic + pub panic: &'a crate::error::ProgramPanic, + } +} + +#[cfg(feature = "repl")] +pub use repl_hook::*; -- cgit