1use crate::private::ArchetypeMetadata;
2use smallvec::SmallVec;
3use std::alloc;
4use std::any::{Any, TypeId};
5use std::ops::Deref;
6
7pub trait ArchetypeState: Send + Sync + 'static {
9 fn ty(&self) -> TypeId;
10 fn as_ptr(&self) -> *const u8;
11 fn forget(self);
12 fn metadata(&self) -> ArchetypeMetadata;
13 fn as_any(&self) -> &dyn Any;
14 fn as_any_mut(&mut self) -> &mut dyn Any;
15 fn num_components(&self) -> usize;
16
17 fn component_ids(&self) -> SmallVec<[TypeId; 32]> {
18 let meta = self.metadata();
19 (meta.component_type_ids)()
20 }
21}
22
23pub trait StaticArchetype: Sized + ArchetypeState {
25 const N_COMPONENTS: usize;
26
27 fn metadata() -> ArchetypeMetadata;
28
29 fn into_any(self) -> AnyState {
30 AnyState(Box::new(self))
31 }
32}
33
34pub struct AnyState(Box<dyn ArchetypeState>);
35
36impl AnyState {
38 pub fn downcast_ref<T: ArchetypeState>(&self) -> Option<&T> {
40 self.0.as_any().downcast_ref()
41 }
42
43 pub fn downcast_mut<T: ArchetypeState>(&mut self) -> Option<&mut T> {
45 self.0.as_any_mut().downcast_mut()
46 }
47
48 pub fn downcast<T: ArchetypeState>(self) -> Option<T> {
50 if let Some(val) = self.downcast_ref::<T>() {
51 let val = unsafe { (val as *const T).read() };
52 self.forget();
53 Some(val)
54 } else {
55 None
56 }
57 }
58}
59
60impl<T: StaticArchetype> From<T> for AnyState {
61 fn from(state: T) -> Self {
62 state.into_any()
63 }
64}
65
66impl ArchetypeState for AnyState {
67 fn ty(&self) -> TypeId {
68 self.0.ty()
69 }
70
71 fn as_ptr(&self) -> *const u8 {
72 self.0.as_ptr()
73 }
74
75 fn forget(self) {
76 let val: &dyn ArchetypeState = self.0.deref();
77 let layout = alloc::Layout::for_value(val);
78 let ptr = Box::into_raw(self.0);
79
80 if layout.size() != 0 {
82 unsafe {
83 assert!(!ptr.is_null());
84 alloc::dealloc(ptr as *mut u8, layout);
85 };
86 }
87 }
88
89 fn metadata(&self) -> ArchetypeMetadata {
90 self.0.metadata()
91 }
92
93 fn as_any(&self) -> &dyn Any {
94 self.0.as_any()
95 }
96
97 fn as_any_mut(&mut self) -> &mut dyn Any {
98 self.0.as_any_mut()
99 }
100
101 fn num_components(&self) -> usize {
102 self.0.num_components()
103 }
104}
105
106impl ArchetypeState for () {
107 fn ty(&self) -> TypeId {
108 TypeId::of::<()>()
109 }
110
111 fn as_ptr(&self) -> *const u8 {
112 self as *const _ as *const u8
113 }
114
115 fn forget(self) {}
116
117 fn metadata(&self) -> ArchetypeMetadata {
118 ArchetypeMetadata {
119 type_id: TypeId::of::<Self>(),
120 component_type_ids: || Default::default(),
121 component_infos: || Default::default(),
122 size: 0,
123 needs_drop: false,
124 drop_fn: |_| {},
125 }
126 }
127
128 fn as_any(&self) -> &dyn Any {
129 self
130 }
131
132 fn as_any_mut(&mut self) -> &mut dyn Any {
133 self
134 }
135
136 fn num_components(&self) -> usize {
137 0
138 }
139}
140
141impl StaticArchetype for () {
142 const N_COMPONENTS: usize = 0;
143
144 fn metadata() -> ArchetypeMetadata {
145 ArchetypeMetadata {
146 type_id: TypeId::of::<Self>(),
147 component_type_ids: || Default::default(),
148 component_infos: || Default::default(),
149 size: 0,
150 needs_drop: false,
151 drop_fn: |_| {},
152 }
153 }
154}