diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-03-29 21:48:23 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-03-29 21:48:23 +0800 |
| commit | 596e5e2440df2d32f1cf3e052dc633e774edf6ee (patch) | |
| tree | dc98eb6a1789847b899207d0b99337bb3ccd92a5 /mingling_core/src/any.rs | |
| parent | 25a164f74c011e6e78846f226cbd7a8bd87db92f (diff) | |
Rename mingling to mingling_core and update dependencies
Diffstat (limited to 'mingling_core/src/any.rs')
| -rw-r--r-- | mingling_core/src/any.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/mingling_core/src/any.rs b/mingling_core/src/any.rs new file mode 100644 index 0000000..1bce96a --- /dev/null +++ b/mingling_core/src/any.rs @@ -0,0 +1,128 @@ +#[cfg(feature = "general_renderer")] +use serde::Serialize; + +use crate::error::ChainProcessError; + +#[derive(Debug)] +pub struct AnyOutput { + inner: Box<dyn std::any::Any + Send + 'static>, + pub type_id: std::any::TypeId, +} + +impl AnyOutput { + #[cfg(feature = "general_renderer")] + pub fn new<T>(value: T) -> Self + where + T: Send + Serialize + 'static, + { + Self { + inner: Box::new(value), + type_id: std::any::TypeId::of::<T>(), + } + } + + #[cfg(not(feature = "general_renderer"))] + pub fn new<T>(value: T) -> Self + where + T: Send + 'static, + { + Self { + inner: Box::new(value), + type_id: std::any::TypeId::of::<T>(), + } + } + + pub fn downcast<T: 'static>(self) -> Result<T, Self> { + if self.type_id == std::any::TypeId::of::<T>() { + Ok(*self.inner.downcast::<T>().unwrap()) + } else { + Err(self) + } + } + + pub fn is<T: 'static>(&self) -> bool { + self.type_id == std::any::TypeId::of::<T>() + } + + /// Route the output to the next Chain + pub fn route_chain(self) -> ChainProcess { + ChainProcess::Ok((self, Next::Chain)) + } + + /// Route the output to the Renderer, ending execution + pub fn route_renderer(self) -> ChainProcess { + ChainProcess::Ok((self, Next::Renderer)) + } +} + +impl std::ops::Deref for AnyOutput { + type Target = dyn std::any::Any + Send + 'static; + + fn deref(&self) -> &Self::Target { + &*self.inner + } +} + +impl std::ops::DerefMut for AnyOutput { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut *self.inner + } +} + +pub enum ChainProcess { + Ok((AnyOutput, Next)), + Err(ChainProcessError), +} + +pub enum Next { + Chain, + Renderer, +} + +impl ChainProcess { + pub fn is_next(&self) -> bool { + matches!(self, Self::Ok(_)) + } + + pub fn is_err(&self) -> bool { + matches!(self, Self::Err(_)) + } + + pub fn next(&self) -> Option<&Next> { + match self { + Self::Ok((_, next)) => Some(next), + Self::Err(_) => None, + } + } + + pub fn err(&self) -> Option<&ChainProcessError> { + match self { + Self::Ok(_) => None, + Self::Err(err) => Some(err), + } + } + + pub fn unwrap(self) -> (AnyOutput, Next) { + match self { + Self::Ok(tuple) => tuple, + Self::Err(_) => panic!("called `ChainProcess2::unwrap()` on an `Error` value"), + } + } + + pub fn unwrap_or(self, default: (AnyOutput, Next)) -> (AnyOutput, Next) { + match self { + Self::Ok(tuple) => tuple, + Self::Err(_) => default, + } + } + + pub fn unwrap_or_else<F>(self, f: F) -> (AnyOutput, Next) + where + F: FnOnce(ChainProcessError) -> (AnyOutput, Next), + { + match self { + Self::Ok(tuple) => tuple, + Self::Err(err) => f(err), + } + } +} |
