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}