1use crate::alloc::alloc::{alloc, dealloc, Layout};
9use crate::alloc::vec::Vec;
10use core::any::TypeId;
11use core::ptr::{self, NonNull};
12
13use hashbrown::hash_map::Entry;
14
15use crate::archetype::{TypeIdMap, TypeInfo};
16use crate::{align, Component, DynamicBundle};
17
18pub struct EntityBuilder<M = ()> {
50 storage: NonNull<u8>,
51 layout: Layout,
52 cursor: usize,
53 info: Vec<(TypeInfo, usize, M)>,
54 ids: Vec<TypeId>,
55 indices: TypeIdMap<usize>,
56}
57
58impl<M> EntityBuilder<M> {
59 pub fn has<T: Component>(&self) -> bool {
61 self.indices.contains_key(&TypeId::of::<T>())
62 }
63
64 pub fn get<T: Component>(&self) -> Option<&T> {
66 let index = self.indices.get(&TypeId::of::<T>())?;
67 let (_, offset, _) = self.info[*index];
68 unsafe {
69 let storage = self.storage.as_ptr().add(offset).cast::<T>();
70 Some(&*storage)
71 }
72 }
73
74 pub fn get_mut<T: Component>(&mut self) -> Option<&mut T> {
76 let index = self.indices.get(&TypeId::of::<T>())?;
77 let (_, offset, _) = self.info[*index];
78 unsafe {
79 let storage = self.storage.as_ptr().add(offset).cast::<T>();
80 Some(&mut *storage)
81 }
82 }
83
84 pub fn component_types(&self) -> impl Iterator<Item = TypeId> + '_ {
86 self.info.iter().map(|(info, _, _)| info.id())
87 }
88
89 unsafe fn grow(
90 min_size: usize,
91 cursor: usize,
92 align: usize,
93 storage: NonNull<u8>,
94 ) -> (NonNull<u8>, Layout) {
95 let layout = Layout::from_size_align(min_size.next_power_of_two().max(64), align).unwrap();
96 let new_storage = NonNull::new_unchecked(alloc(layout));
97 ptr::copy_nonoverlapping(storage.as_ptr(), new_storage.as_ptr(), cursor);
98 (new_storage, layout)
99 }
100
101 pub fn clear(&mut self) {
106 self.ids.clear();
107 self.indices.clear();
108 self.cursor = 0;
109 unsafe {
110 for (ty, offset, _) in self.info.drain(..) {
111 ty.drop(self.storage.as_ptr().add(offset));
112 }
113 }
114 }
115
116 unsafe fn add_inner(&mut self, ptr: *mut u8, ty: TypeInfo, meta: M) {
117 match self.indices.entry(ty.id()) {
118 Entry::Occupied(occupied) => {
119 let index = *occupied.get();
120 let (ty, offset, _) = self.info[index];
121 let storage = self.storage.as_ptr().add(offset);
122
123 ty.drop(storage);
125
126 ptr::copy_nonoverlapping(ptr, storage, ty.layout().size());
128 }
129 Entry::Vacant(vacant) => {
130 let offset = align(self.cursor, ty.layout().align());
131 let end = offset + ty.layout().size();
132 if end > self.layout.size() || ty.layout().align() > self.layout.align() {
133 let new_align = self.layout.align().max(ty.layout().align());
134 let (new_storage, new_layout) =
135 Self::grow(end, self.cursor, new_align, self.storage);
136 if self.layout.size() != 0 {
137 dealloc(self.storage.as_ptr(), self.layout);
138 }
139 self.storage = new_storage;
140 self.layout = new_layout;
141 }
142
143 let addr = self.storage.as_ptr().add(offset);
144 ptr::copy_nonoverlapping(ptr, addr, ty.layout().size());
145
146 vacant.insert(self.info.len());
147 self.info.push((ty, offset, meta));
148 self.cursor = end;
149 }
150 }
151 }
152}
153
154impl EntityBuilder<()> {
155 pub fn new() -> Self {
157 Self::default()
158 }
159
160 pub fn add<T: Component>(&mut self, component: T) -> &mut Self {
165 self.add_bundle((component,))
166 }
167
168 pub fn add_bundle(&mut self, bundle: impl DynamicBundle) -> &mut Self {
174 unsafe {
175 bundle.put(|ptr, ty| self.add_inner(ptr, ty, ()));
176 }
177 self
178 }
179
180 pub fn build(&mut self) -> BuiltEntity<'_> {
182 self.info.sort_unstable_by_key(|x| x.0);
183 self.ids.extend(self.info.iter().map(|x| x.0.id()));
184 BuiltEntity { builder: self }
185 }
186}
187
188impl EntityBuilder<Cloneable> {
189 pub fn new_cloneable() -> Self {
192 Self::default()
193 }
194
195 pub fn add<T: Component + Clone>(&mut self, mut component: T) -> &mut Self {
200 unsafe {
201 self.add_inner(
202 (&mut component as *mut T).cast(),
203 TypeInfo::of::<T>(),
204 Cloneable::new::<T>(),
205 );
206 core::mem::forget(component);
207 }
208 self
209 }
210
211 pub fn build(self) -> ReusableBuiltEntity {
214 self.into()
215 }
216}
217
218impl Clone for EntityBuilder<Cloneable> {
219 fn clone(&self) -> Self {
220 unsafe {
221 let result = Self {
222 storage: NonNull::new_unchecked(alloc(self.layout)),
223 layout: self.layout,
224 cursor: self.cursor,
225 info: self.info.clone(),
226 ids: Vec::new(),
227 indices: self.indices.clone(),
228 };
229 for &(_, offset, ref clone) in &self.info {
230 (clone.0)(self.storage.as_ptr().add(offset), &mut |src, ty| {
231 result
232 .storage
233 .as_ptr()
234 .add(offset)
235 .copy_from_nonoverlapping(src, ty.layout().size())
236 });
237 }
238 result
239 }
240 }
241}
242
243unsafe impl<M> Send for EntityBuilder<M> {}
244unsafe impl<M> Sync for EntityBuilder<M> {}
245
246impl<M> Drop for EntityBuilder<M> {
247 fn drop(&mut self) {
248 self.clear();
250 if self.layout.size() != 0 {
251 unsafe {
252 dealloc(self.storage.as_ptr(), self.layout);
253 }
254 }
255 }
256}
257
258impl<M> Default for EntityBuilder<M> {
259 fn default() -> Self {
261 Self {
262 storage: NonNull::dangling(),
263 layout: Layout::from_size_align(0, 8).unwrap(),
264 cursor: 0,
265 info: Vec::new(),
266 ids: Vec::new(),
267 indices: Default::default(),
268 }
269 }
270}
271
272#[derive(Clone)]
274pub struct Cloneable(unsafe fn(*const u8, &mut dyn FnMut(*mut u8, TypeInfo)));
275
276impl Cloneable {
277 fn new<T: Component + Clone>() -> Self {
278 Self(|src, f| unsafe {
279 let mut tmp = (*src.cast::<T>()).clone();
280 f((&mut tmp as *mut T).cast(), TypeInfo::of::<T>());
281 core::mem::forget(tmp);
282 })
283 }
284}
285
286pub struct BuiltEntity<'a> {
289 builder: &'a mut EntityBuilder<()>,
290}
291
292unsafe impl DynamicBundle for BuiltEntity<'_> {
293 fn with_ids<T>(&self, f: impl FnOnce(&[TypeId]) -> T) -> T {
294 f(&self.builder.ids)
295 }
296
297 #[doc(hidden)]
298 fn type_info(&self) -> Vec<TypeInfo> {
299 self.builder.info.iter().map(|x| x.0).collect()
300 }
301
302 unsafe fn put(self, mut f: impl FnMut(*mut u8, TypeInfo)) {
303 for (ty, offset, ()) in self.builder.info.drain(..) {
304 let ptr = self.builder.storage.as_ptr().add(offset);
305 f(ptr, ty);
306 }
307 }
308}
309
310impl Drop for BuiltEntity<'_> {
311 fn drop(&mut self) {
312 self.builder.clear();
315 }
316}
317
318#[derive(Clone)]
322pub struct ReusableBuiltEntity(EntityBuilder<Cloneable>);
323
324unsafe impl DynamicBundle for &'_ ReusableBuiltEntity {
325 fn with_ids<T>(&self, f: impl FnOnce(&[TypeId]) -> T) -> T {
326 f(&self.0.ids)
327 }
328
329 fn type_info(&self) -> Vec<TypeInfo> {
330 self.0.info.iter().map(|x| x.0).collect()
331 }
332
333 unsafe fn put(self, mut f: impl FnMut(*mut u8, TypeInfo)) {
334 for &(_, offset, ref clone) in &self.0.info {
335 let ptr = self.0.storage.as_ptr().add(offset);
336 (clone.0)(ptr, &mut f);
337 }
338 }
339}
340
341impl From<EntityBuilder<Cloneable>> for ReusableBuiltEntity {
342 fn from(mut x: EntityBuilder<Cloneable>) -> Self {
343 x.info.sort_unstable_by_key(|y| y.0);
344 x.ids.extend(x.info.iter().map(|y| y.0.id()));
345 Self(x)
346 }
347}
348
349impl From<ReusableBuiltEntity> for EntityBuilder<Cloneable> {
350 fn from(mut x: ReusableBuiltEntity) -> Self {
351 x.0.ids.clear();
352 x.0
353 }
354}