summaryrefslogtreecommitdiff
path: root/mingling/src/any.rs
blob: 204a7e3165b5908e59239d6d9964f0cd38039f55 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#[cfg(feature = "general_renderer")]
use serde::Serialize;

use crate::error::ChainProcessError;

pub type ChainProcess = Result<AnyOutput, 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 {
        Ok(self)
    }

    /// Route the output to the Renderer, ending execution
    pub fn route_renderer(self) -> ChainProcess {
        Err(ChainProcessError::Broken(self))
    }
}

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
    }
}