diff options
Diffstat (limited to 'mingling/src')
| -rw-r--r-- | mingling/src/lib.rs | 2 | ||||
| -rw-r--r-- | mingling/src/program.rs | 2 | ||||
| -rw-r--r-- | mingling/src/program/exec.rs | 33 | ||||
| -rw-r--r-- | mingling/src/program/hint.rs | 32 |
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(¤t) { + 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(¤t) { + 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) + } +} |
