diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-04-08 22:48:31 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-04-08 22:53:52 +0800 |
| commit | 240361b240d638363346013160b0943b47769c37 (patch) | |
| tree | dbe2316a670faf961fffe3c6764eff440e5230a2 | |
| parent | 6e2d660e310a44d441266ae32a5800db52d48049 (diff) | |
Implement mingling::this functionmain
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | mingling_core/Cargo.toml | 2 | ||||
| -rw-r--r-- | mingling_core/src/asset/dispatcher.rs | 72 | ||||
| -rw-r--r-- | mingling_core/src/program.rs | 75 | ||||
| -rw-r--r-- | mingling_core/src/program/exec.rs | 10 |
5 files changed, 115 insertions, 45 deletions
@@ -173,6 +173,7 @@ name = "mingling_core" version = "0.1.4" dependencies = [ "just_fmt", + "once_cell", "ron", "serde", "serde_json", diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml index d8e7c8e..e978401 100644 --- a/mingling_core/Cargo.toml +++ b/mingling_core/Cargo.toml @@ -23,6 +23,8 @@ serde = { version = "1.0", features = ["derive"], optional = true } thiserror = "2" tokio = { version = "1", features = ["io-std", "io-util"] } +once_cell = "1.21.4" + ron = { version = "0.12.1", optional = true } serde_json = { version = "1", optional = true } serde_yaml = { version = "0.9", optional = true } diff --git a/mingling_core/src/asset/dispatcher.rs b/mingling_core/src/asset/dispatcher.rs index 86dfe7c..0f4675c 100644 --- a/mingling_core/src/asset/dispatcher.rs +++ b/mingling_core/src/asset/dispatcher.rs @@ -34,7 +34,7 @@ impl<C: crate::program::ProgramCollect, G: Display> Program<C, G> { /// Adds a dispatcher to the program. pub fn with_dispatcher<Disp>(&mut self, dispatcher: Disp) where - Disp: Dispatcher<G> + 'static, + Disp: Dispatcher<G> + Send + Sync + 'static, { self.dispatcher.push(Box::new(dispatcher)); } @@ -60,17 +60,17 @@ impl<C: crate::program::ProgramCollect, G: Display> Program<C, G> { /// allowing multiple dispatchers to be grouped together and passed /// to the program via `Program::with_dispatchers`. pub struct Dispatchers<G> { - dispatcher: Vec<Box<dyn Dispatcher<G> + 'static>>, + dispatcher: Vec<Box<dyn Dispatcher<G> + Send + Sync + 'static>>, } -impl<G> From<Vec<Box<dyn Dispatcher<G>>>> for Dispatchers<G> { - fn from(dispatcher: Vec<Box<dyn Dispatcher<G>>>) -> Self { +impl<G> From<Vec<Box<dyn Dispatcher<G> + Send + Sync>>> for Dispatchers<G> { + fn from(dispatcher: Vec<Box<dyn Dispatcher<G> + Send + Sync>>) -> Self { Self { dispatcher } } } -impl<G> From<Box<dyn Dispatcher<G>>> for Dispatchers<G> { - fn from(dispatcher: Box<dyn Dispatcher<G>>) -> Self { +impl<G> From<Box<dyn Dispatcher<G> + Send + Sync>> for Dispatchers<G> { + fn from(dispatcher: Box<dyn Dispatcher<G> + Send + Sync>) -> Self { Self { dispatcher: vec![dispatcher], } @@ -79,7 +79,7 @@ impl<G> From<Box<dyn Dispatcher<G>>> for Dispatchers<G> { impl<D, G> From<(D,)> for Dispatchers<G> where - D: Dispatcher<G> + 'static, + D: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatcher: (D,)) -> Self { @@ -91,8 +91,8 @@ where impl<D1, D2, G> From<(D1, D2)> for Dispatchers<G> where - D1: Dispatcher<G> + 'static, - D2: Dispatcher<G> + 'static, + D1: Dispatcher<G> + Send + Sync + 'static, + D2: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatchers: (D1, D2)) -> Self { @@ -104,9 +104,9 @@ where impl<D1, D2, D3, G> From<(D1, D2, D3)> for Dispatchers<G> where - D1: Dispatcher<G> + 'static, - D2: Dispatcher<G> + 'static, - D3: Dispatcher<G> + 'static, + D1: Dispatcher<G> + Send + Sync + 'static, + D2: Dispatcher<G> + Send + Sync + 'static, + D3: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3)) -> Self { @@ -122,10 +122,10 @@ where impl<D1, D2, D3, D4, G> From<(D1, D2, D3, D4)> for Dispatchers<G> where - D1: Dispatcher<G> + 'static, - D2: Dispatcher<G> + 'static, - D3: Dispatcher<G> + 'static, - D4: Dispatcher<G> + 'static, + D1: Dispatcher<G> + Send + Sync + 'static, + D2: Dispatcher<G> + Send + Sync + 'static, + D3: Dispatcher<G> + Send + Sync + 'static, + D4: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4)) -> Self { @@ -142,11 +142,11 @@ where impl<D1, D2, D3, D4, D5, G> From<(D1, D2, D3, D4, D5)> for Dispatchers<G> where - D1: Dispatcher<G> + 'static, - D2: Dispatcher<G> + 'static, - D3: Dispatcher<G> + 'static, - D4: Dispatcher<G> + 'static, - D5: Dispatcher<G> + 'static, + D1: Dispatcher<G> + Send + Sync + 'static, + D2: Dispatcher<G> + Send + Sync + 'static, + D3: Dispatcher<G> + Send + Sync + 'static, + D4: Dispatcher<G> + Send + Sync + 'static, + D5: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4, D5)) -> Self { @@ -164,12 +164,12 @@ where impl<D1, D2, D3, D4, D5, D6, G> From<(D1, D2, D3, D4, D5, D6)> for Dispatchers<G> where - D1: Dispatcher<G> + 'static, - D2: Dispatcher<G> + 'static, - D3: Dispatcher<G> + 'static, - D4: Dispatcher<G> + 'static, - D5: Dispatcher<G> + 'static, - D6: Dispatcher<G> + 'static, + D1: Dispatcher<G> + Send + Sync + 'static, + D2: Dispatcher<G> + Send + Sync + 'static, + D3: Dispatcher<G> + Send + Sync + 'static, + D4: Dispatcher<G> + Send + Sync + 'static, + D5: Dispatcher<G> + Send + Sync + 'static, + D6: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4, D5, D6)) -> Self { @@ -188,13 +188,13 @@ where impl<D1, D2, D3, D4, D5, D6, D7, G> From<(D1, D2, D3, D4, D5, D6, D7)> for Dispatchers<G> where - D1: Dispatcher<G> + 'static, - D2: Dispatcher<G> + 'static, - D3: Dispatcher<G> + 'static, - D4: Dispatcher<G> + 'static, - D5: Dispatcher<G> + 'static, - D6: Dispatcher<G> + 'static, - D7: Dispatcher<G> + 'static, + D1: Dispatcher<G> + Send + Sync + 'static, + D2: Dispatcher<G> + Send + Sync + 'static, + D3: Dispatcher<G> + Send + Sync + 'static, + D4: Dispatcher<G> + Send + Sync + 'static, + D5: Dispatcher<G> + Send + Sync + 'static, + D6: Dispatcher<G> + Send + Sync + 'static, + D7: Dispatcher<G> + Send + Sync + 'static, G: Display, { fn from(dispatchers: (D1, D2, D3, D4, D5, D6, D7)) -> Self { @@ -213,14 +213,14 @@ where } impl<G> std::ops::Deref for Dispatchers<G> { - type Target = Vec<Box<dyn Dispatcher<G> + 'static>>; + type Target = Vec<Box<dyn Dispatcher<G> + Send + Sync + 'static>>; fn deref(&self) -> &Self::Target { &self.dispatcher } } -impl<G> From<Dispatchers<G>> for Vec<Box<dyn Dispatcher<G> + 'static>> { +impl<G> From<Dispatchers<G>> for Vec<Box<dyn Dispatcher<G> + Send + Sync + 'static>> { fn from(val: Dispatchers<G>) -> Self { val.dispatcher } diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index 0a24001..8c8b4cb 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -4,7 +4,7 @@ use crate::{ AnyOutput, ChainProcess, RenderResult, asset::dispatcher::Dispatcher, error::ProgramExecuteError, }; -use std::{env, fmt::Display, pin::Pin}; +use std::{env, fmt::Display, pin::Pin, sync::OnceLock}; #[doc(hidden)] pub mod exec; @@ -18,6 +18,28 @@ mod flag; pub use flag::*; use tokio::io::AsyncWriteExt; +/// Global static reference to the current program instance +static THIS_PROGRAM: OnceLock<Option<Box<dyn std::any::Any + Send + Sync>>> = OnceLock::new(); + +/// Returns a reference to the current program instance, panics if not set. +pub fn this<C>() -> &'static Program<C, C> +where + C: ProgramCollect + Display + 'static, +{ + try_get_this_program().expect("Program not initialized") +} + +/// Returns a reference to the current program instance, if set. +fn try_get_this_program<C>() -> Option<&'static Program<C, C>> +where + C: ProgramCollect + Display + 'static, +{ + THIS_PROGRAM + .get()? + .as_ref()? + .downcast_ref::<Program<C, C>>() +} + /// Program, used to define the behavior of the entire command-line program #[derive(Default)] pub struct Program<C, G> @@ -29,7 +51,7 @@ where pub(crate) group: std::marker::PhantomData<G>, pub(crate) args: Vec<String>, - pub(crate) dispatcher: Vec<Box<dyn Dispatcher<G>>>, + pub(crate) dispatcher: Vec<Box<dyn Dispatcher<G> + Send + Sync>>, pub stdout_setting: ProgramStdoutSetting, pub user_context: ProgramUserContext, @@ -58,14 +80,57 @@ where } } + /// Returns a reference to the current program instance, if set. + pub async fn this_program() -> &'static Program<C, G> + where + C: 'static, + G: 'static, + { + THIS_PROGRAM + .get() + .unwrap() + .as_ref() + .unwrap() + .downcast_ref::<Program<C, G>>() + .unwrap() + } + + /// Sets the current program instance and runs the provided async function. + async fn set_instance_and_run<F, Fut>(self, f: F) -> Fut::Output + where + C: 'static + Send + Sync, + G: 'static + Send + Sync, + F: FnOnce(&'static Program<C, G>) -> Fut + Send + Sync, + Fut: Future + Send, + { + THIS_PROGRAM.get_or_init(|| Some(Box::new(self))); + let program = THIS_PROGRAM + .get() + .unwrap() + .as_ref() + .unwrap() + .downcast_ref::<Program<C, G>>() + .unwrap(); + f(program).await + } + /// Run the command line program - pub async fn exec_without_render(mut self) -> Result<RenderResult, ProgramExecuteError> { + pub async fn exec_without_render(mut self) -> Result<RenderResult, ProgramExecuteError> + where + C: 'static + Send + Sync, + G: 'static + Send + Sync, + { self.args = self.args.iter().skip(1).cloned().collect(); - crate::exec::exec(self).await.map_err(|e| e.into()) + self.set_instance_and_run(|p| async { crate::exec::exec(p).await.map_err(|e| e.into()) }) + .await } /// Run the command line program - pub async fn exec(self) { + pub async fn exec(self) + where + C: 'static + Send + Sync, + G: 'static + Send + Sync, + { let stdout_setting = self.stdout_setting.clone(); let result = match self.exec_without_render().await { Ok(r) => r, diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs index 1a4f6ff..f578064 100644 --- a/mingling_core/src/program/exec.rs +++ b/mingling_core/src/program/exec.rs @@ -10,7 +10,9 @@ use crate::{ #[doc(hidden)] pub mod error; -pub async fn exec<C, G>(program: Program<C, G>) -> Result<RenderResult, ProgramInternalExecuteError> +pub async fn exec<C, G>( + program: &Program<C, G>, +) -> Result<RenderResult, ProgramInternalExecuteError> where C: ProgramCollect<Enum = G>, G: Display, @@ -73,7 +75,7 @@ where #[allow(clippy::type_complexity)] fn match_user_input<C, G>( program: &Program<C, G>, -) -> Result<(&Box<dyn Dispatcher<G>>, Vec<String>), ProgramInternalExecuteError> +) -> Result<(&Box<dyn Dispatcher<G> + Send + Sync>, Vec<String>), ProgramInternalExecuteError> where C: ProgramCollect<Enum = G>, G: Display, @@ -82,7 +84,7 @@ where let command = format!("{} ", program.args.join(" ")); // Find all nodes that match the command prefix - let matching_nodes: Vec<&(String, &Box<dyn Dispatcher<G>>)> = nodes + let matching_nodes: Vec<&(String, &Box<dyn Dispatcher<G> + Send + Sync>)> = nodes .iter() // Also add a space to the node string to ensure consistent matching logic .filter(|(node_str, _)| command.starts_with(&format!("{} ", node_str))) @@ -142,7 +144,7 @@ fn render<C: ProgramCollect<Enum = G>, G: Display>( // Get all registered dispatcher names from the program fn get_nodes<C: ProgramCollect<Enum = G>, G: Display>( program: &Program<C, G>, -) -> Vec<(String, &Box<dyn Dispatcher<G>>)> { +) -> Vec<(String, &Box<dyn Dispatcher<G> + Send + Sync>)> { program .dispatcher .iter() |
