summaryrefslogtreecommitdiff
path: root/mingling/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-03-29 14:06:50 +0800
committer魏曹先生 <1992414357@qq.com>2026-03-29 14:06:50 +0800
commit5d91f0e9408e39afaa75f96b32c5ed7946a558f7 (patch)
tree01ded24e80c1f07067adc882d547a69773d43c6d /mingling/src
parent7809a8cbfbaf41fcc81de980c903e11f08bd1b12 (diff)
Add fallback dispatcher for missing renderers.
Diffstat (limited to 'mingling/src')
-rw-r--r--mingling/src/lib.rs2
-rw-r--r--mingling/src/program.rs2
-rw-r--r--mingling/src/program/exec.rs33
-rw-r--r--mingling/src/program/hint.rs32
4 files changed, 63 insertions, 6 deletions
diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs
index 060fa30..4d9bcc5 100644
--- a/mingling/src/lib.rs
+++ b/mingling/src/lib.rs
@@ -20,7 +20,7 @@ pub mod hint {
pub mod macros {
pub use mingling_macros::chain;
pub use mingling_macros::chain_struct;
- pub use mingling_macros::dispatcher_chain;
+ pub use mingling_macros::dispatcher;
pub use mingling_macros::dispatcher_render;
pub use mingling_macros::node;
pub use mingling_macros::program;
diff --git a/mingling/src/program.rs b/mingling/src/program.rs
index 5e9d1f2..3394a38 100644
--- a/mingling/src/program.rs
+++ b/mingling/src/program.rs
@@ -81,6 +81,8 @@ where
pub trait ProgramCollect {
fn render(any: AnyOutput, r: &mut RenderResult);
fn do_chain(any: AnyOutput) -> Pin<Box<dyn Future<Output = ChainProcess> + Send>>;
+ fn has_renderer(any: &AnyOutput) -> bool;
+ fn has_chain(any: &AnyOutput) -> bool;
}
#[macro_export]
diff --git a/mingling/src/program/exec.rs b/mingling/src/program/exec.rs
index 99eb419..04ed16d 100644
--- a/mingling/src/program/exec.rs
+++ b/mingling/src/program/exec.rs
@@ -1,7 +1,7 @@
use crate::{
AnyOutput, ChainProcess, Dispatcher, Program, ProgramCollect, RenderResult,
error::{ChainProcessError, ProgramInternalExecuteError},
- hint::{DispatcherNotFound, NoChainFound, ProgramEnd},
+ hint::{DispatcherNotFound, NoChainFound, ProgramEnd, RendererNotFound},
};
pub mod error;
@@ -30,10 +30,33 @@ pub async fn exec<C: ProgramCollect>(
};
loop {
- current = match handle_chain_process::<C>(C::do_chain(current).await) {
- Ok(Next::RenderResult(render_result)) => return Ok(render_result),
- Ok(Next::AnyOutput(any)) => any,
- Err(e) => return Err(e),
+ current = {
+ // If a chain exists, execute as a chain
+ if C::has_chain(&current) {
+ match handle_chain_process::<C>(C::do_chain(current).await) {
+ Ok(Next::RenderResult(render_result)) => return Ok(render_result),
+ Ok(Next::AnyOutput(any)) => any,
+ Err(e) => return Err(e),
+ }
+ }
+ // If no chain exists, attempt to render
+ else if C::has_renderer(&current) {
+ let mut render_result = RenderResult::default();
+ C::render(current, &mut render_result);
+ return Ok(render_result);
+ }
+ // If no renderer exists, transfer to the RendererNotFound Dispatcher for execution
+ else {
+ let disp: Box<dyn Dispatcher> = Box::new(RendererNotFound);
+ let any = match handle_chain_process::<C>(
+ disp.begin(vec![format!("{:?}", current.type_id)]),
+ ) {
+ Ok(Next::AnyOutput(any)) => any,
+ Ok(Next::RenderResult(result)) => return Ok(result),
+ Err(e) => return Err(e),
+ };
+ any
+ }
};
if current.is::<ProgramEnd>() || current.is::<NoChainFound>() {
break;
diff --git a/mingling/src/program/hint.rs b/mingling/src/program/hint.rs
index e9c510b..bf35fea 100644
--- a/mingling/src/program/hint.rs
+++ b/mingling/src/program/hint.rs
@@ -50,3 +50,35 @@ impl Dispatcher for DispatcherNotFound {
Box::new(DispatcherNotFound)
}
}
+
+/// Marker: Renderer Not Found
+///
+/// If a Chain outputs NoRendererFound to the Chain,
+/// the program will terminate directly.
+///
+/// You can implement Renderer for NoRendererFound
+/// to render relevant information when a Renderer cannot be found.
+#[cfg_attr(feature = "serde_renderer", derive(serde::Serialize))]
+pub struct NoRendererFound {
+ pub type_to_render: String,
+}
+
+#[derive(Default)]
+#[cfg_attr(feature = "serde_renderer", derive(serde::Serialize))]
+pub struct RendererNotFound;
+impl Dispatcher for RendererNotFound {
+ fn node(&self) -> crate::Node {
+ Node::default().join("_not_found")
+ }
+
+ fn begin(&self, args: Vec<String>) -> ChainProcess {
+ AnyOutput::new(NoRendererFound {
+ type_to_render: args.get(0).unwrap().clone(),
+ })
+ .route_renderer()
+ }
+
+ fn clone_dispatcher(&self) -> Box<dyn Dispatcher> {
+ Box::new(RendererNotFound)
+ }
+}