1use core::fmt;
2use std::{
3 any::{Any, TypeId},
4 cmp::Ordering,
5 fmt::Debug,
6 marker::PhantomData,
7};
8
9use downcast_rs::Downcast;
10use parking_lot::MappedRwLockReadGuard;
11use serde::{
12 self,
13 de::{self, DeserializeSeed},
14 Deserialize, Serialize,
15};
16
17use crate::{
18 component_traits::IComponentBuffer, with_component_registry, AttributeGuard, AttributeStoreGuard, AttributeStoreGuardMut,
19 ComponentAttribute, ComponentEntry, ComponentPath, ComponentVTable, Debuggable, Description, Name, Serializable,
20};
21
22pub trait ComponentValueBase: Send + Sync + Downcast + 'static {
23 fn type_name(&self) -> &'static str {
24 std::any::type_name::<Self>()
25 }
26}
27
28impl<T: Send + Sync + 'static> ComponentValueBase for T {}
29pub trait ComponentValue: ComponentValueBase + Clone {}
30impl<T: ComponentValueBase + Clone> ComponentValue for T {}
31
32pub struct Component<T: 'static> {
34 desc: ComponentDesc,
35 _marker: PhantomData<T>,
36}
37
38impl<T: 'static> From<ComponentDesc> for Component<T> {
39 fn from(value: ComponentDesc) -> Self {
40 Self::new(value)
41 }
42}
43
44impl<T: 'static> From<Component<T>> for ComponentDesc {
45 #[inline]
46 fn from(value: Component<T>) -> Self {
47 value.desc
48 }
49}
50
51impl<T: 'static> std::ops::Deref for Component<T> {
52 type Target = ComponentDesc;
53
54 #[inline]
55 fn deref(&self) -> &Self::Target {
56 &self.desc
57 }
58}
59
60impl<T> Debug for Component<T> {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.debug_struct("Component").field("path", &self.path()).field("index", &self.desc.index).finish()
63 }
64}
65
66impl Debug for ComponentDesc {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_struct("ComponentDesc").field("path", &self.path()).field("index", &self.index).finish_non_exhaustive()
69 }
70}
71
72impl<T: 'static> Component<T> {
73 #[inline]
75 pub fn desc(&self) -> ComponentDesc {
76 self.desc
77 }
78}
79
80impl<T> Clone for Component<T> {
81 fn clone(&self) -> Self {
82 Self { desc: self.desc, _marker: PhantomData }
83 }
84}
85
86impl<T> Copy for Component<T> {}
87
88impl<T> PartialEq for Component<T> {
89 fn eq(&self, other: &Self) -> bool {
90 self.desc.index == other.index
91 }
92}
93
94impl<T> Eq for Component<T> {}
95
96impl<T> PartialEq<ComponentDesc> for Component<T> {
97 fn eq(&self, other: &ComponentDesc) -> bool {
98 self.desc.index == other.index
99 }
100}
101
102impl<T> PartialEq<Component<T>> for ComponentDesc {
103 fn eq(&self, other: &Component<T>) -> bool {
104 self.index == other.desc.index
105 }
106}
107
108impl<T> PartialOrd for Component<T> {
109 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
110 self.desc.index.partial_cmp(&other.desc.index)
111 }
112}
113
114impl<T> Ord for Component<T> {
115 fn cmp(&self, other: &Self) -> Ordering {
116 self.desc.index.cmp(&other.desc.index)
117 }
118}
119
120impl<T: ComponentValue> std::hash::Hash for Component<T> {
121 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
122 self.index().hash(state);
123 }
124}
125
126impl<T> Component<T> {
127 pub fn new(desc: ComponentDesc) -> Self {
132 if !desc.is::<T>() {
133 panic!(
134 "Attempt to convert component description of {:?} into component of type {:?}",
135 desc.type_name(),
136 std::any::type_name::<T>()
137 );
138 }
139 Self { desc, _marker: PhantomData }
140 }
141
142 pub fn as_debug<'a>(&self, value: &'a T) -> &'a dyn Debug {
143 self.desc.as_debug(value)
144 }
145}
146
147#[repr(C)]
149#[derive(Clone, Copy)]
150pub struct ComponentDesc {
151 index: u32,
152 pub(crate) vtable: &'static ComponentVTable<()>,
153}
154
155impl Eq for ComponentDesc {}
156
157impl std::hash::Hash for ComponentDesc {
158 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
159 self.index.hash(state);
160 }
161}
162
163impl PartialEq for ComponentDesc {
164 fn eq(&self, other: &Self) -> bool {
165 self.index == other.index
166 }
167}
168
169impl PartialOrd for ComponentDesc {
170 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
171 self.index.partial_cmp(&other.index)
172 }
173}
174impl Ord for ComponentDesc {
175 fn cmp(&self, other: &Self) -> Ordering {
176 self.index.cmp(&other.index)
177 }
178}
179
180impl ComponentDesc {
181 pub fn path(&self) -> String {
183 if let Some(path) = self.vtable.path {
184 path.to_string()
185 } else {
186 self.attribute::<ComponentPath>().expect("No path for component").0.clone()
187 }
188 }
189
190 pub fn path_last(&self) -> String {
192 if let Some(path) = self.vtable.path {
193 path.rsplit_once("::").map(|v| v.1).unwrap_or(path).into()
194 } else {
195 let path = &self.attribute::<ComponentPath>().expect("No path for component").0;
196 path.rsplit_once("::").map(|v| v.1).unwrap_or(path).into()
197 }
198 }
199
200 pub fn name(&self) -> Option<String> {
202 Some(self.attribute::<Name>()?.0.clone())
203 }
204
205 pub fn description(&self) -> Option<String> {
207 Some(self.attribute::<Description>()?.0.clone())
208 }
209
210 pub fn type_name(&self) -> &'static str {
211 (self.vtable.get_type_name)()
212 }
213
214 pub fn type_id(&self) -> TypeId {
215 (self.vtable.get_type_id)()
216 }
217
218 #[inline]
219 pub fn is<T: 'static>(&self) -> bool {
221 (self.vtable.get_type_id)() == TypeId::of::<T>()
222 }
223
224 pub(crate) fn new(index: u32, vtable: &'static ComponentVTable<()>) -> Self {
225 Self { index, vtable }
226 }
227
228 pub fn has_attribute<A: ComponentAttribute>(&self) -> bool {
229 (self.vtable.attributes)(*self).has::<A>()
230 }
231
232 pub fn attribute<A: ComponentAttribute>(&self) -> Option<AttributeGuard<A>> {
233 let guard = (self.vtable.attributes)(*self);
234 MappedRwLockReadGuard::try_map(guard, |store| store.get::<A>()).ok()
235 }
236
237 pub fn attributes(&self) -> AttributeStoreGuard {
238 (self.vtable.attributes)(*self)
239 }
240
241 pub fn attributes_mut(&self) -> AttributeStoreGuardMut {
242 (self.vtable.attributes_init)(*self)
243 }
244
245 pub fn as_debug<'a>(&self, value: &'a dyn Any) -> &'a dyn Debug {
246 struct NoDebug;
247 impl Debug for NoDebug {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 f.write_str("...")
250 }
251 }
252
253 if let Some(v) = self.attribute::<Debuggable>() {
254 v.as_debug(value)
255 } else {
256 &NoDebug
257 }
258 }
259
260 pub fn index(&self) -> u32 {
261 self.index
262 }
263
264 pub fn from_json(&self, value: &str) -> Result<ComponentEntry, serde_json::Error> {
265 self.attribute::<Serializable>()
266 .expect("Component is not serializable")
267 .deserializer(*self)
268 .deserialize(&mut serde_json::de::Deserializer::from_str(value))
269 }
270
271 pub fn to_json(&self, value: &ComponentEntry) -> Result<String, serde_json::Error> {
273 serde_json::to_string(self.attribute::<Serializable>().expect("Component is not serializable").serialize(value))
274 }
275
276 pub fn create_buffer(&self) -> Box<dyn IComponentBuffer> {
277 (self.vtable.impl_create_buffer)(*self)
278 }
279}
280
281impl Serialize for ComponentDesc {
282 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
283 serializer.serialize_str(&self.path())
284 }
285}
286
287impl<'de> Deserialize<'de> for ComponentDesc {
288 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
289 where
290 D: serde::Deserializer<'de>,
291 {
292 struct BoxIComponentVisitor;
293
294 impl<'de> serde::de::Visitor<'de> for BoxIComponentVisitor {
295 type Value = ComponentDesc;
296
297 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
298 formatter.write_str("struct ComponentDesc")
299 }
300 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
301 where
302 E: de::Error,
303 {
304 let component = with_component_registry(|r| r.get_by_path(v));
305 match component {
306 Some(comp) => Ok(comp),
307 None => Err(de::Error::custom(format!("No such component: {v}"))),
308 }
309 }
310 }
311
312 deserializer.deserialize_str(BoxIComponentVisitor)
313 }
314}
315
316#[macro_export]
317macro_rules! components {
322 ($ns: literal, { $($(#[$outer:meta])* $(@[$($attr: ty$([ $params: expr ])?),*])? $vis: vis $name:ident: $ty:ty,)*}) => {
323 $(
324 $crate::paste::paste! {
325 #[allow(non_upper_case_globals)]
326 #[doc(hidden)]
327 static [<comp_ $name>]: $crate::OnceCell<$crate::ComponentDesc> = $crate::OnceCell::new();
328
329 #[doc(hidden)]
330 fn [< __init_component_ $name>] (reg: &mut $crate::ComponentRegistry) -> $crate::ComponentDesc {
331 fn init_attr(_component: $crate::Component<$ty>) -> $crate::parking_lot::RwLock<$crate::AttributeStore> {
332
333 #[allow(unused_mut)]
334 let mut store = $crate::AttributeStore::new();
335
336
337 $( $(
338 <$attr as $crate::AttributeConstructor::<$ty, _>>::construct(
339 &mut store,
340 ($($params),*)
341 );
342 )*)*
343
344 $crate::parking_lot::RwLock::new(store)
345
346 }
347
348 static ATTRIBUTES: $crate::OnceCell<$crate::parking_lot::RwLock<$crate::AttributeStore>> = $crate::OnceCell::new();
349
350 static PATH: &str = concat!("core::", $ns, "::", stringify!($name));
351
352 static VTABLE: &$crate::ComponentVTable<$ty> = &$crate::ComponentVTable::construct(
353 PATH,
354 |desc| $crate::parking_lot::RwLockReadGuard::map(ATTRIBUTES.get_or_init(|| init_attr($crate::Component::new(desc))).read(), |v| v),
355 |desc| $crate::parking_lot::RwLockWriteGuard::map(ATTRIBUTES.get_or_init(|| init_attr($crate::Component::new(desc))).write(), |v| v)
356 );
357
358 *[<comp_ $name>].get_or_init(|| {
359 reg.register_static(PATH, unsafe { VTABLE.erase() } )
360 })
361 }
362
363 $(#[$outer])*
364 pub fn $name() -> $crate::Component<$ty> {
365
366 let desc = *[<comp_ $name>].get()
367 .expect(concat!("Component: ", "core::", $ns, "::", stringify!($name), " is not initialized"));
368
369 $crate::Component::new(desc)
370 }
371 }
372 )*
373
374
375 pub fn init_components() {
377 let mut reg = $crate::ComponentRegistry::get_mut();
378 $(
379 $crate::paste::paste! {
380 [< __init_component_ $name>](&mut reg);
381 }
382 )*
383 }
384
385 }
386}
387
388#[cfg(test)]
389mod test {
390 use std::{ptr, sync::Arc};
391
392 use once_cell::sync::Lazy;
393 use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
394 use serde::de::DeserializeSeed;
395
396 use super::*;
397 use crate::{AttributeStore, ComponentVTable, MakeDefault, Networked, Store};
398
399 #[test]
400 fn manual_component() {
401 static ATTRIBUTES: Lazy<RwLock<AttributeStore>> = Lazy::new(Default::default);
402 static VTABLE: &ComponentVTable<String> = &ComponentVTable::construct(
403 "core::test::my_component",
404 |_| RwLockReadGuard::map(ATTRIBUTES.read(), |v| v),
405 |_| RwLockWriteGuard::map(ATTRIBUTES.write(), |v| v),
406 );
407
408 let component: Component<String> = Component::new(ComponentDesc::new(1, unsafe { VTABLE.erase() }));
409
410 let value = ComponentEntry::new(component, "Hello, World".into());
411
412 let value2 = value.clone();
413
414 let s = value.downcast_ref::<String>();
415 let s2 = value2.downcast_ref::<String>();
416
417 assert!(!ptr::eq(s as *const String, s2 as *const String));
419 assert_eq!(value.downcast_ref::<String>(), value2.downcast_ref::<String>());
421
422 assert_eq!(value.try_downcast_ref::<&str>(), None);
423 }
424
425 #[derive(PartialEq, Eq, Debug, Clone, serde::Serialize, serde::Deserialize)]
426 pub struct Person {
427 name: String,
428 age: i32,
429 }
430
431 #[test]
432 fn component_macro() {
433 components! ("component_macro",{
434 @[Serializable, Debuggable]
435 foo: String,
436 @[Serializable, Debuggable]
438 person: Person,
439 });
440
441 init_components();
442
443 let component = foo();
444
445 assert_eq!(component.path_last(), "foo");
446
447 assert!(component.has_attribute::<Serializable>());
448
449 let p = Person { name: "Adam".into(), age: 28 };
450 let entry = ComponentEntry::new(person(), p);
451
452 let str = serde_json::to_string_pretty(entry.attribute::<Serializable>().unwrap().serialize(&entry)).unwrap();
453
454 eprintln!("Serialized: {str}");
455
456 let ser = person().attribute::<Serializable>().unwrap();
457
458 let value: ComponentEntry = ser.deserializer(person().desc()).deserialize(&mut serde_json::Deserializer::from_str(&str)).unwrap();
459
460 eprintln!("Value: {:?}", value.as_debug());
461
462 let p = entry.into_inner::<Person>();
463 assert_eq!(value.downcast_ref::<Person>(), &p);
464 assert_eq!(value.try_downcast_ref::<String>(), None);
465 }
466
467 #[test]
468 fn make_default() {
469 fn default_person() -> Person {
470 Person { age: 21, name: "unnamed".into() }
471 }
472
473 components! ("make_default", {
474 @[MakeDefault, Debuggable]
475 people: Vec<Person>,
476 @[MakeDefault[default_person], Debuggable, Store, Networked]
477 person: Person,
478 });
479 init_components();
480
481 let people_desc: ComponentDesc = people().desc();
482 let person_desc: ComponentDesc = person().desc();
483
484 let mut people = people_desc.attribute::<MakeDefault>().unwrap().make_default(people_desc);
485
486 let mut person = person_desc.attribute::<MakeDefault>().unwrap().make_default(person_desc);
487
488 assert_eq!(person.downcast_ref::<Person>(), &Person { age: 21, name: "unnamed".into() });
489
490 people.downcast_mut::<Vec<Person>>().push(person.downcast_cloned::<Person>());
491
492 assert_eq!(&people.downcast_mut::<Vec<Person>>()[0], person.downcast_ref::<Person>());
493 person.downcast_mut::<Person>().name = "Smith".to_string();
494 assert_ne!(&people.downcast_mut::<Vec<Person>>()[0], person.downcast_ref::<Person>());
495
496 eprintln!("people: {people:?}, person: {person:?}");
497 }
498
499 #[test]
500 fn test_take() {
501 components! ("test_take", {
502 @[Store]
503 my_component: Arc<String>,
504 });
505
506 init_components();
507 let shared = Arc::new("Foo".to_string());
508
509 {
510 let value = ComponentEntry::new(my_component(), shared.clone());
511 let value2 = ComponentEntry::new(my_component(), shared.clone());
512
513 assert_eq!(Arc::strong_count(&shared), 3);
514 drop(value);
515 assert_eq!(Arc::strong_count(&shared), 2);
516
517 let value = value2.into_inner::<Arc<String>>();
518 assert_eq!(Arc::strong_count(&shared), 2);
519 drop(value);
520 assert_eq!(Arc::strong_count(&shared), 1);
521 }
522
523 assert_eq!(Arc::strong_count(&shared), 1);
524 }
525
526 #[test]
527 fn leak_test() {
528 let shared = Arc::new("Foo".to_string());
529
530 components! ("leak_test", {
531 my_component: Arc<String>,
532 });
533
534 init_components();
535
536 {
537 let value = ComponentEntry::new(my_component(), shared.clone());
538 let value2 = ComponentEntry::new(my_component(), shared.clone());
539
540 assert_eq!(Arc::strong_count(&shared), 3);
541 drop(value);
542 assert_eq!(Arc::strong_count(&shared), 2);
543
544 let value3 = value2.clone();
545 let value4: Arc<String> = value2.downcast_cloned();
546 assert_eq!(Arc::strong_count(&shared), 4);
547 drop(value4);
548 assert_eq!(Arc::strong_count(&shared), 3);
549
550 assert_eq!(value3.downcast_ref::<Arc<String>>(), &shared);
551 assert_eq!(value3.downcast_ref::<Arc<String>>(), value2.downcast_ref());
552
553 assert!(!ptr::eq(value3.downcast_ref::<Arc<String>>() as *const Arc<String>, &shared as *const _));
554 assert!(!ptr::eq(value3.downcast_ref::<Arc<String>>() as *const Arc<String>, value2.downcast_ref::<Arc<String>>() as *const _));
555
556 assert!(ptr::eq(&**value3.downcast_ref::<Arc<String>>() as *const String, &*shared as *const _));
557 }
558
559 assert_eq!(Arc::strong_count(&shared), 1);
560 }
561}