1pub trait ResourceTag: std::fmt::Debug + downcast_rs::DowncastSync + 'static {}
3
4pub trait Resource: ResourceTag {
5 fn clone_resource(&self) -> Box<dyn Resource>;
6}
7
8impl<T: ResourceTag + Clone> Resource for T {
9 fn clone_resource(&self) -> Box<dyn Resource> {
10 Box::new(self.clone())
11 }
12}
13
14downcast_rs::impl_downcast!(sync Resource);
15
16impl Clone for Box<dyn Resource> {
17 fn clone(&self) -> Self {
18 self.clone_resource()
19 }
20}
21
22#[derive(Clone)]
23#[repr(transparent)]
24pub(crate) struct BoxedResource(Box<dyn Resource>);
25
26impl BoxedResource {
27 pub(crate) fn as_ref<R: Resource>(&self) -> &R {
28 self.0.as_any().downcast_ref::<R>().unwrap()
29 }
30
31 pub(crate) fn as_mut<R: Resource>(&mut self) -> &mut R {
32 self.0.as_any_mut().downcast_mut::<R>().unwrap()
33 }
34}
35
36impl std::fmt::Debug for BoxedResource {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
38 self.0.fmt(f)
39 }
40}
41
42#[derive(Clone)]
43pub struct BoxedEntry {
44 pub(crate) id: AnyId,
45 pub(crate) value: BoxedResource,
46}
47
48impl BoxedEntry {
49 pub(crate) fn new(r: impl Resource) -> Self {
50 let id = AnyId::from(&r);
51 let value = BoxedResource(Box::new(r));
52 BoxedEntry { id, value }
53 }
54}
55
56impl<R: Resource> From<R> for BoxedEntry {
57 fn from(inner: R) -> Self {
58 BoxedEntry::new(inner)
59 }
60}
61
62#[derive(Copy, Clone)]
63pub(crate) struct AnyId {
64 type_id: std::any::TypeId,
65 #[cfg(debug_assertions)]
66 type_name: &'static str,
67}
68
69impl AnyId {
70 pub(crate) fn of<A: ?Sized + 'static>() -> Self {
71 Self {
72 type_id: std::any::TypeId::of::<A>(),
73 #[cfg(debug_assertions)]
74 type_name: std::any::type_name::<A>(),
75 }
76 }
77}
78
79impl PartialEq for AnyId {
80 fn eq(&self, other: &Self) -> bool {
81 self.type_id == other.type_id
82 }
83}
84
85impl Eq for AnyId {}
86
87impl PartialOrd for AnyId {
88 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
89 Some(self.cmp(other))
90 }
91}
92
93impl Ord for AnyId {
94 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
95 self.type_id.cmp(&other.type_id)
96 }
97}
98
99impl std::hash::Hash for AnyId {
100 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
101 self.type_id.hash(state);
102 }
103}
104
105impl std::fmt::Debug for AnyId {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
107 #[cfg(not(debug_assertions))]
108 {
109 self.type_id.fmt(f)
110 }
111 #[cfg(debug_assertions)]
112 {
113 f.debug_tuple(self.type_name).field(&self.type_id).finish()
114 }
115 }
116}
117
118impl<'a, A: ?Sized + 'static> From<&'a A> for AnyId {
119 fn from(_: &'a A) -> Self {
120 Self::of::<A>()
121 }
122}