vine_core/core/
ty.rs

1use std::any::{Any, type_name, TypeId};
2use std::fmt::{Debug, Display, Formatter};
3use std::sync::Arc;
4
5
6use dashmap::DashMap;
7use lazy_static::lazy_static;
8use log::{trace, warn};
9
10
11use crate::core::{DynBean, Error};
12
13pub struct Type {
14    id: TypeId,
15    name: &'static str,
16    downcast_fns: Arc<DashMap<TypeId, Arc<dyn Any + Send + Sync>>>
17}
18
19lazy_static!(
20    static ref TYPES: Arc<DashMap<TypeId, Arc<Type>>> = Arc::new(DashMap::new());
21);
22
23impl Type {
24    pub fn of<T: 'static>() -> Arc<Type> {
25        let type_id = TypeId::of::<T>();
26        let ref_mut = TYPES.entry(type_id).or_insert_with(|| {
27            let name = type_name::<T>();
28
29            trace!("register Type({})", name);
30            Arc::new(Type {
31                id: TypeId::of::<T>(),
32                name,
33                downcast_fns: Default::default(),
34            })
35        });
36
37        ref_mut.clone()
38    }
39
40    pub fn name(&self) -> &str {
41        self.name
42    }
43
44    pub fn id(&self) -> &TypeId {
45        &self.id
46    }
47
48    pub fn assignable(&self, type_id: &TypeId) -> bool {
49        self.downcast_fns.contains_key(type_id)
50    }
51
52
53    pub fn add_downcast<T: ?Sized + 'static>(&self, downcast_fn: fn(DynBean) -> Result<Arc<T>, DynBean>) {
54        let alias_id = TypeId::of::<T>();
55        trace!("register {} downcast fn for {}", self, type_name::<T>());
56        if let Some(_) = self.downcast_fns.insert(alias_id, Arc::new(downcast_fn)) {
57            warn!("override {} downcast fn for {}", self, type_name::<T>());
58        }
59    }
60
61    pub fn downcast<T: ?Sized + 'static>(dyn_bean: DynBean) -> Result<Arc<T>, Error> {
62        let type_id = dyn_bean.as_ref().type_id();
63        let Some(type_ref) = TYPES.get(&type_id) else {
64            return Err(Error::from("{:?} is not registered in vine Type System"))
65        };
66
67        let alias_id = TypeId::of::<T>();
68        let Some(downcast_fn) = type_ref.value().downcast_fns.get(&alias_id) else {
69            return Err(Error::from("TODO 111"))
70        };
71
72        let arc = downcast_fn.clone()
73            .downcast::<fn(DynBean) -> Result<Arc<T>, DynBean>>()
74            .unwrap();
75
76        let Ok(bean) = (arc.as_ref())(dyn_bean) else {
77            return Err(Error::from("TODO 2"))
78        };
79
80        Ok(bean)
81    }
82}
83
84impl Display for Type {
85    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
86        write!(f, "Type({})", self.name)
87    }
88}
89
90
91impl Debug for Type {
92    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
93        write!(f, "Type(id={:?}, name={:?}, downcast_fns.len()={})", &self.id, self.name, self.downcast_fns.len())
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use std::sync::Arc;
100
101    use crate::core::DynBean;
102    use crate::core::ty::Type;
103
104    struct TestBean { name: &'static str, }
105    trait TestTrait { fn name(&self) -> &'static str; }
106    impl TestTrait for TestBean {
107        fn name(&self) -> &'static str { self.name }
108    }
109
110    #[test]
111    fn should_be_thread_safe() {
112        let ty = Type::of::<TestBean>();
113        ty.add_downcast::<TestBean>(|b| { Ok(Arc::downcast::<TestBean>(b)?)});
114        ty.add_downcast::<dyn TestTrait + Sync + Send>(|b| { Ok(Arc::downcast::<TestBean>(b)?)});
115
116        let given_dyn_bean: DynBean = Arc::new(TestBean { name: "test_bean" });
117
118        let test_bean = Type::downcast::<TestBean>(given_dyn_bean.clone()).unwrap();
119        let test_trait = Type::downcast::<dyn TestTrait + Send + Sync>(given_dyn_bean.clone()).unwrap();
120
121        assert_eq!(test_trait.name(), test_bean.name);
122    }
123}