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 {
22 id: TypeId,
24 name: &'static str,
26 downcast_fns: Arc<DashMap<TypeId, Arc<dyn Any + Send + Sync>>>
28}
29
30lazy_static!(
32 static ref TYPES: Arc<DashMap<TypeId, Arc<Type>>> = Arc::new(DashMap::new());
33);
34
35impl Type {
36 pub fn of<T: 'static>() -> Arc<Type> {
49 let type_id = TypeId::of::<T>();
50 let ref_mut = TYPES.entry(type_id).or_insert_with(|| {
51 let name = type_name::<T>();
52
53 trace!("register Type({})", name);
54 Arc::new(Type {
55 id: TypeId::of::<T>(),
56 name,
57 downcast_fns: Default::default(),
58 })
59 });
60
61 ref_mut.clone()
62 }
63
64 pub fn name(&self) -> &str {
66 self.name
67 }
68
69 pub fn id(&self) -> &TypeId {
71 &self.id
72 }
73
74 pub fn assignable(&self, type_id: &TypeId) -> bool {
79 self.downcast_fns.contains_key(type_id)
80 }
81
82
83 pub fn add_downcast<T: ?Sized + 'static>(&self, downcast_fn: fn(DynBean) -> Result<Arc<T>, DynBean>) {
100 let alias_id = TypeId::of::<T>();
101 trace!("register {} downcast fn for {}", self, type_name::<T>());
102 if let Some(_) = self.downcast_fns.insert(alias_id, Arc::new(downcast_fn)) {
103 warn!("override {} downcast fn for {}", self, type_name::<T>());
104 }
105 }
106
107 pub fn downcast<T: ?Sized + 'static>(dyn_bean: DynBean) -> Result<Arc<T>, Error> {
130 let type_id = dyn_bean.as_ref().type_id();
131 let Some(type_ref) = TYPES.get(&type_id) else {
132 return Err(Error::from(format!("Type {:?} is not registered in vine Type System", type_id)))
133 };
134
135 let alias_id = TypeId::of::<T>();
136 let Some(downcast_fn) = type_ref.value().downcast_fns.get(&alias_id) else {
137 return Err(Error::from(format!("No downcast function registered for {} -> {}", type_ref.value().name(), type_name::<T>())))
138 };
139
140 let arc = downcast_fn.clone()
141 .downcast::<fn(DynBean) -> Result<Arc<T>, DynBean>>()
142 .unwrap();
143
144 let Ok(bean) = (arc.as_ref())(dyn_bean) else {
145 return Err(Error::from(format!("Failed to downcast {} to {}", type_ref.value().name(), type_name::<T>())))
146 };
147
148 Ok(bean)
149 }
150}
151
152impl Display for Type {
153 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
154 write!(f, "Type({})", self.name)
155 }
156}
157
158
159impl Debug for Type {
160 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
161 write!(f, "Type(id={:?}, name={:?}, downcast_fns.len()={})", &self.id, self.name, self.downcast_fns.len())
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use std::sync::Arc;
168
169 use crate::core::DynBean;
170 use crate::core::ty::Type;
171
172 struct TestBean { name: &'static str, }
173 trait TestTrait { fn name(&self) -> &'static str; }
174 impl TestTrait for TestBean {
175 fn name(&self) -> &'static str { self.name }
176 }
177
178 #[test]
179 fn should_be_thread_safe() {
180 let ty = Type::of::<TestBean>();
181 ty.add_downcast::<TestBean>(|b| { Ok(Arc::downcast::<TestBean>(b)?)});
182 ty.add_downcast::<dyn TestTrait + Sync + Send>(|b| { Ok(Arc::downcast::<TestBean>(b)?)});
183
184 let given_dyn_bean: DynBean = Arc::new(TestBean { name: "test_bean" });
185
186 let test_bean = Type::downcast::<TestBean>(given_dyn_bean.clone()).unwrap();
187 let test_trait = Type::downcast::<dyn TestTrait + Send + Sync>(given_dyn_bean.clone()).unwrap();
188
189 assert_eq!(test_trait.name(), test_bean.name);
190 }
191}