1use alloc::{sync::Arc, vec, vec::Vec};
4use core::{
5 alloc::Layout,
6 any::{type_name, Any, TypeId},
7 borrow::{Borrow, BorrowMut},
8 marker::PhantomData,
9 mem::{transmute, ManuallyDrop},
10 ptr::{self, drop_in_place, slice_from_raw_parts_mut, NonNull},
11};
12
13use hashbrown::hash_map::{Entry, HashMap};
14
15use crate::{action::LocalActionEncoder, entity::EntityId, hash::NoOpHasherBuilder, type_id};
16
17pub use edict_proc::Component;
18
19#[doc(hidden)]
20pub type BorrowFn<T> = for<'r> unsafe fn(NonNull<u8>, PhantomData<&'r T>) -> &'r T;
21
22#[doc(hidden)]
23pub type BorrowFnMut<T> = for<'r> unsafe fn(NonNull<u8>, PhantomData<&'r mut T>) -> &'r mut T;
24
25#[derive(Clone, Copy)]
27pub struct ComponentBorrow {
28 ty: TypeId,
29
30 borrow: BorrowFn<()>,
32
33 borrow_mut: Option<BorrowFnMut<()>>,
35}
36
37#[doc(hidden)]
39pub mod private {
40 use core::borrow::{Borrow, BorrowMut};
41
42 use super::ComponentBorrow;
43
44 pub struct DispatchBorrowMut<T, U>(pub DispatchBorrow<T, U>);
45
46 pub struct DispatchBorrow<T, U>(pub core::marker::PhantomData<(T, U)>);
47
48 impl<T, U> core::ops::Deref for DispatchBorrowMut<T, U> {
49 type Target = DispatchBorrow<T, U>;
50
51 fn deref(&self) -> &DispatchBorrow<T, U> {
52 &self.0
53 }
54 }
55
56 impl<T, U> DispatchBorrowMut<T, U>
57 where
58 T: BorrowMut<U> + Send + Sync + 'static,
59 U: 'static,
60 {
61 pub fn insert(&self, extend: &mut impl core::iter::Extend<ComponentBorrow>) {
62 extend.extend(Some(ComponentBorrow::make(
63 |ptr: core::ptr::NonNull<u8>, core::marker::PhantomData| -> &U {
64 unsafe { ptr.cast::<T>().as_ref().borrow() }
65 },
66 core::option::Option::Some(
67 |ptr: core::ptr::NonNull<u8>, core::marker::PhantomData| -> &mut U {
68 unsafe { ptr.cast::<T>().as_mut().borrow_mut() }
69 },
70 ),
71 )));
72 }
73 }
74
75 impl<T, U> DispatchBorrow<T, U>
76 where
77 T: Borrow<U> + Sync + 'static,
78 U: 'static,
79 {
80 pub fn insert(&self, extend: &mut impl core::iter::Extend<ComponentBorrow>) {
81 extend.extend(Some(ComponentBorrow::make(
82 |ptr: core::ptr::NonNull<u8>, core::marker::PhantomData| -> &U {
83 unsafe { ptr.cast::<T>().as_ref().borrow() }
84 },
85 core::option::Option::None,
86 )));
87 }
88 }
89
90 impl<T, U> DispatchBorrowMut<T, U> {
91 pub fn new() -> Self {
92 DispatchBorrowMut(DispatchBorrow(core::marker::PhantomData::<(T, U)>))
93 }
94 }
95
96 #[macro_export]
99 macro_rules! type_borrow {
100 ($self:ty as $other:ty => $borrows:ident) => {
101 let dispatch = $crate::component::private::DispatchBorrowMut::<$self, $other>::new();
102 dispatch.insert(&mut $borrows);
103 };
104 }
105
106 #[macro_export]
109 macro_rules! trait_borrow {
110 ($self:ty as $trait:path => $borrows:ident) => {{
111 struct DispatchTraitBorrowSendSync<T> { send: DispatchTraitBorrowSend<T> }
112 struct DispatchTraitBorrowSend<T>{ sync: DispatchTraitBorrowSync<T> }
113 struct DispatchTraitBorrowSync<T>{ bare: DispatchTraitBorrow<T> }
114 struct DispatchTraitBorrow<T>(core::marker::PhantomData<T>);
115
116 impl<T> core::ops::Deref for DispatchTraitBorrowSendSync<T> {
117 type Target = DispatchTraitBorrowSend<T>;
118
119 fn deref(&self) -> &DispatchTraitBorrowSend<T> {
120 &self.send
121 }
122 }
123
124 impl<T> core::ops::Deref for DispatchTraitBorrowSend<T> {
125 type Target = DispatchTraitBorrowSync<T>;
126
127 fn deref(&self) -> &DispatchTraitBorrowSync<T> {
128 &self.sync
129 }
130 }
131
132 impl<T> core::ops::Deref for DispatchTraitBorrowSync<T> {
133 type Target = DispatchTraitBorrow<T>;
134
135 fn deref(&self) -> &DispatchTraitBorrow<T> {
136 &self.bare
137 }
138 }
139
140 impl<T> DispatchTraitBorrowSendSync<T> {
141 fn new() -> Self {
142 DispatchTraitBorrowSendSync {
143 send: DispatchTraitBorrowSend {
144 sync: DispatchTraitBorrowSync {
145 bare: DispatchTraitBorrow(core::marker::PhantomData::<T>),
146 },
147 },
148
149 }
150 }
151 }
152
153 impl<T: $trait + $crate::private::Send + $crate::private::Sync + 'static> DispatchTraitBorrowSendSync<T> {
154 #[allow(unused)]
155 fn insert(
156 &self,
157 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
158 ) {
159 self.insert_one(extend);
160 self.send.insert_one(extend);
161 self.sync.insert_one(extend);
162 self.bare.insert_one(extend);
163 }
164
165 #[allow(unused)]
166 fn insert_one(
167 &self,
168 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
169 ) {
170 extend.extend(Some($crate::component::ComponentBorrow::make(
171 |ptr: $crate::private::NonNull<u8>,
172 $crate::private::PhantomData|
173 -> &(dyn $trait + $crate::private::Send + $crate::private::Sync) {
174 unsafe { ptr.cast::<T>().as_ref() }
175 },
176 $crate::private::Option::Some(
177 |ptr: $crate::private::NonNull<u8>,
178 $crate::private::PhantomData|
179 -> &mut (dyn $trait + $crate::private::Send + $crate::private::Sync) {
180 unsafe { ptr.cast::<T>().as_mut() }
181 },
182 ),
183 )));
184 }
185 }
186
187 impl<T: $trait + $crate::private::Send + 'static> DispatchTraitBorrowSend<T> {
188 #[allow(unused)]
189 fn insert(
190 &self,
191 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
192 ) {
193 self.insert_one(extend);
194 self.bare.insert_one(extend);
195 }
196
197 #[allow(unused)]
198 fn insert_one(
199 &self,
200 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
201 ) {
202 extend.extend(Some($crate::component::ComponentBorrow::make(
203 |ptr: $crate::private::NonNull<u8>,
204 $crate::private::PhantomData|
205 -> &(dyn $trait + Send) {
206 unsafe { ptr.cast::<T>().as_ref() }
207 },
208 $crate::private::Option::Some(
209 |ptr: $crate::private::NonNull<u8>,
210 $crate::private::PhantomData|
211 -> &mut (dyn $trait + Send) {
212 unsafe { ptr.cast::<T>().as_mut() }
213 },
214 ),
215 )));
216 }
217 }
218
219 impl<T: $trait + $crate::private::Sync + 'static> DispatchTraitBorrowSync<T> {
220 #[allow(unused)]
221 fn insert(
222 &self,
223 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
224 ) {
225 self.insert_one(extend);
226 self.bare.insert_one(extend);
227 }
228
229 #[allow(unused)]
230 fn insert_one(
231 &self,
232 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
233 ) {
234 extend.extend(Some($crate::component::ComponentBorrow::make(
235 |ptr: $crate::private::NonNull<u8>,
236 $crate::private::PhantomData|
237 -> &(dyn $trait + Sync) {
238 unsafe { ptr.cast::<T>().as_ref() }
239 },
240 $crate::private::Option::Some(
241 |ptr: $crate::private::NonNull<u8>,
242 $crate::private::PhantomData|
243 -> &mut (dyn $trait + Sync) {
244 unsafe { ptr.cast::<T>().as_mut() }
245 },
246 ),
247 )));
248 }
249 }
250
251 impl<T: $trait + 'static> DispatchTraitBorrow<T> {
252 #[allow(unused)]
253 fn insert(
254 &self,
255 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
256 ) {
257 self.insert_one(extend);
258 }
259
260 fn insert_one(
261 &self,
262 extend: &mut $crate::private::Vec<$crate::component::ComponentBorrow>,
263 ) {
264 extend.extend(Some($crate::component::ComponentBorrow::make(
265 |ptr: $crate::private::NonNull<u8>, $crate::private::PhantomData| -> &dyn $trait {
266 unsafe { ptr.cast::<T>().as_ref() }
267 },
268 $crate::private::Option::Some(
269 |ptr: $crate::private::NonNull<u8>,
270 $crate::private::PhantomData|
271 -> &mut dyn $trait {
272 unsafe { ptr.cast::<T>().as_mut() }
273 },
274 ),
275 )));
276 }
277 }
278
279 let dispatch = DispatchTraitBorrowSendSync::<$self>::new();
280 dispatch.insert(&mut $borrows);
281 }};
282 }
283}
284
285impl ComponentBorrow {
286 #[doc(hidden)]
289 pub fn make<T: ?Sized + 'static>(
290 borrow: BorrowFn<T>,
291 borrow_mut: Option<BorrowFnMut<T>>,
292 ) -> Self {
293 ComponentBorrow {
294 ty: type_id::<T>(),
295 borrow: unsafe { transmute(borrow) },
296 borrow_mut: borrow_mut.map(|f| unsafe { transmute(f) }),
297 }
298 }
299
300 pub fn from_borrow<T, U>() -> Self
303 where
304 T: Borrow<U> + 'static,
305 U: ?Sized + 'static,
306 {
307 ComponentBorrow::make(|ptr, PhantomData| unsafe { ptr.cast::<T>().as_ref() }, None)
308 }
309
310 pub fn from_borrow_mut<T, U>() -> Self
313 where
314 T: Component + BorrowMut<U>,
315 U: ?Sized + 'static,
316 {
317 ComponentBorrow::make(
318 |ptr, PhantomData| unsafe { ptr.cast::<T>().as_ref() },
319 Some(|ptr, PhantomData| unsafe { ptr.cast::<T>().as_mut() }),
320 )
321 }
322
323 pub fn auto<T>() -> Self
325 where
326 T: 'static,
327 {
328 ComponentBorrow::make(
329 |ptr, PhantomData| unsafe { ptr.cast::<T>().as_ref() },
330 Some(|ptr, PhantomData| unsafe { ptr.cast::<T>().as_mut() }),
331 )
332 }
333
334 pub(crate) fn target(&self) -> TypeId {
335 self.ty
336 }
337
338 pub(crate) fn borrow<'a, T: ?Sized + 'static>(&self) -> BorrowFn<T> {
339 debug_assert!(self.ty == type_id::<T>());
340 unsafe { transmute(self.borrow) }
341 }
342
343 pub(crate) fn has_borrow_mut(&self) -> bool {
344 self.borrow_mut.is_some()
345 }
346
347 pub(crate) fn borrow_mut<'a, T: ?Sized + 'static>(&self) -> Option<BorrowFnMut<T>> {
348 debug_assert!(self.ty == type_id::<T>());
349 unsafe { self.borrow_mut.map(|f| transmute(f)) }
350 }
351}
352
353pub trait Component: Sized + 'static {
365 #[inline(always)]
367 fn name() -> &'static str {
368 core::any::type_name::<Self>()
369 }
370
371 #[inline(always)]
373 fn on_drop(&mut self, id: EntityId, encoder: LocalActionEncoder) {
374 let _ = id;
375 let _ = encoder;
376 }
377
378 #[inline(always)]
381 fn on_replace(&mut self, value: &Self, id: EntityId, encoder: LocalActionEncoder) -> bool
382 where
383 Self: Sized,
384 {
385 let _ = value;
386 let _ = id;
387 let _ = encoder;
388 true
389 }
390
391 #[inline(always)]
393 fn borrows() -> Vec<ComponentBorrow> {
394 vec![ComponentBorrow::auto::<Self>()]
395 }
396}
397
398#[derive(Clone)]
400pub struct ComponentInfo {
401 ty: TypeId,
403
404 layout: Layout,
406
407 name: &'static str,
409
410 drop_one: DropOneFn,
413
414 on_drop: Arc<dyn Any + Send + Sync>,
416
417 set_one: SetOneFn,
420
421 on_replace: Arc<dyn Any + Send + Sync>,
423
424 final_drop: FinalDrop,
427
428 borrows: Arc<[ComponentBorrow]>,
430}
431
432impl ComponentInfo {
433 #[inline(always)]
435 pub fn of<T>() -> Self
436 where
437 T: Component,
438 {
439 ComponentInfo {
440 ty: type_id::<T>(),
441 layout: Layout::new::<T>(),
442 name: T::name(),
443 drop_one: drop_one::<T, DefaultDropHook>,
444 on_drop: Arc::new(DefaultDropHook),
445 set_one: set_one::<T, DefaultSetHook, DefaultDropHook>,
446 on_replace: Arc::new(DefaultSetHook),
447 final_drop: final_drop::<T>,
448 borrows: Arc::from(T::borrows()),
449 }
450 }
451
452 #[inline(always)]
454 pub fn external<T>() -> Self
455 where
456 T: 'static,
457 {
458 ComponentInfo {
459 ty: type_id::<T>(),
460 layout: Layout::new::<T>(),
461 name: type_name::<T>(),
462 drop_one: drop_one::<T, ExternalDropHook>,
463 on_drop: Arc::new(ExternalDropHook),
464 set_one: set_one::<T, ExternalSetHook, ExternalDropHook>,
465 on_replace: Arc::new(ExternalSetHook),
466 final_drop: final_drop::<T>,
467 borrows: vec![ComponentBorrow::auto::<T>()].into(),
468 }
469 }
470
471 #[inline(always)]
472 pub fn id(&self) -> TypeId {
473 self.ty
474 }
475
476 #[inline(always)]
477 pub fn layout(&self) -> Layout {
478 self.layout
479 }
480
481 #[inline(always)]
482 pub fn name(&self) -> &'static str {
483 self.name
484 }
485
486 #[inline(always)]
487 pub fn borrows(&self) -> &[ComponentBorrow] {
488 &self.borrows
489 }
490
491 #[inline(always)]
492 pub fn has_borrow(&self, ty: TypeId) -> bool {
493 self.borrows.iter().any(|b| b.target() == ty)
494 }
495
496 #[inline(always)]
497 pub fn has_borrow_mut(&self, ty: TypeId) -> bool {
498 self.borrows
499 .iter()
500 .find(|b| b.target() == ty)
501 .map_or(false, |b| b.has_borrow_mut())
502 }
503
504 #[inline(always)]
505 pub(crate) fn drop_one(&self, ptr: NonNull<u8>, id: EntityId, encoder: LocalActionEncoder) {
506 unsafe {
507 (self.drop_one)(NonNull::from(&*self.on_drop).cast(), ptr, id, encoder);
508 }
509 }
510
511 #[inline(always)]
512 pub(crate) fn set_one(
513 &self,
514 dst: NonNull<u8>,
515 src: NonNull<u8>,
516 id: EntityId,
517 encoder: LocalActionEncoder,
518 ) {
519 unsafe {
520 (self.set_one)(
521 NonNull::from(&*self.on_replace).cast(),
522 NonNull::from(&*self.on_drop).cast(),
523 dst,
524 src,
525 id,
526 encoder,
527 );
528 }
529 }
530
531 #[inline(always)]
532 pub(crate) fn final_drop(&self, ptr: NonNull<u8>, count: usize) {
533 unsafe {
534 (self.final_drop)(ptr, count);
535 }
536 }
537}
538
539pub trait DropHook<T: ?Sized>: Send + Sync + 'static {
542 fn on_drop(&self, component: &mut T, id: EntityId, encoder: LocalActionEncoder);
544}
545
546impl<T, F> DropHook<T> for F
547where
548 T: ?Sized,
549 F: Fn(&mut T, EntityId, LocalActionEncoder) + Send + Sync + 'static,
550{
551 #[inline(always)]
552 fn on_drop(&self, component: &mut T, id: EntityId, encoder: LocalActionEncoder) {
553 self(component, id, encoder);
554 }
555}
556
557pub trait SetHook<T: ?Sized>: Send + Sync + 'static {
560 fn on_replace(
563 &self,
564 component: &mut T,
565 value: &T,
566 id: EntityId,
567 encoder: LocalActionEncoder,
568 ) -> bool;
569}
570
571impl<T, F> SetHook<T> for F
572where
573 T: ?Sized,
574 F: Fn(&mut T, &T, EntityId, LocalActionEncoder) -> bool + Send + Sync + 'static,
575{
576 #[inline(always)]
577 fn on_replace(
578 &self,
579 component: &mut T,
580 value: &T,
581 id: EntityId,
582 encoder: LocalActionEncoder,
583 ) -> bool {
584 self(component, value, id, encoder)
585 }
586}
587
588#[derive(Clone, Copy, Debug)]
590pub struct DefaultDropHook;
591
592impl<T> DropHook<T> for DefaultDropHook
593where
594 T: Component,
595{
596 #[inline(always)]
597 fn on_drop(&self, component: &mut T, id: EntityId, encoder: LocalActionEncoder) {
598 T::on_drop(component, id, encoder);
599 }
600}
601
602#[derive(Clone, Copy, Debug)]
604pub struct DefaultSetHook;
605
606impl<T> SetHook<T> for DefaultSetHook
607where
608 T: Component,
609{
610 #[inline(always)]
611 fn on_replace(&self, dst: &mut T, src: &T, id: EntityId, encoder: LocalActionEncoder) -> bool {
612 T::on_replace(dst, src, id, encoder)
613 }
614}
615
616#[derive(Clone, Copy, Debug)]
618pub struct ExternalDropHook;
619
620impl<T> DropHook<T> for ExternalDropHook {
621 #[inline(always)]
622 fn on_drop(&self, _component: &mut T, _id: EntityId, _encoder: LocalActionEncoder) {}
623}
624
625#[derive(Clone, Copy, Debug)]
627pub struct ExternalSetHook;
628
629impl<T> SetHook<T> for ExternalSetHook {
630 #[inline(always)]
631 fn on_replace(
632 &self,
633 _dst: &mut T,
634 _src: &T,
635 _entity: EntityId,
636 _encoder: LocalActionEncoder,
637 ) -> bool {
638 true
639 }
640}
641
642pub struct ComponentInfoRef<
645 'a,
646 T: 'static,
647 D: DropHook<T> = DefaultDropHook,
648 S: SetHook<T> = DefaultSetHook,
649> {
650 info: Option<&'a mut ComponentInfo>,
651 phantom: PhantomData<T>,
652 drop: ManuallyDrop<D>,
653 set: ManuallyDrop<S>,
654 name: Option<&'static str>,
655}
656
657impl<T, D, S> Drop for ComponentInfoRef<'_, T, D, S>
658where
659 T: 'static,
660 D: DropHook<T>,
661 S: SetHook<T>,
662{
663 #[inline(always)]
664 fn drop(&mut self) {
665 self.drop_impl();
666 }
667}
668
669impl<'a, T, D, S> ComponentInfoRef<'a, T, D, S>
670where
671 T: 'static,
672 D: DropHook<T>,
673 S: SetHook<T>,
674{
675 #[inline(always)]
676 fn drop_impl(&mut self) {
677 let info = self.info.as_mut().unwrap();
678 info.drop_one = drop_one::<T, D>;
679 info.on_drop = Arc::new(unsafe { ManuallyDrop::take(&mut self.drop) });
680 info.set_one = set_one::<T, S, D>;
681 info.on_replace = Arc::new(unsafe { ManuallyDrop::take(&mut self.set) });
682 if let Some(name) = self.name {
683 info.name = name;
684 }
685 }
686
687 pub fn finish(self) -> &'a ComponentInfo {
690 let mut me = ManuallyDrop::new(self);
691 me.drop_impl();
692 me.info.take().unwrap()
693 }
694
695 pub fn on_drop<F>(self, hook: F) -> ComponentInfoRef<'a, T, F, S>
700 where
701 F: DropHook<T>,
702 {
703 let me = ManuallyDrop::new(self);
704
705 ComponentInfoRef {
706 info: unsafe { ptr::read(&me.info) },
707 phantom: me.phantom,
708 drop: ManuallyDrop::new(hook),
709 set: unsafe { ptr::read(&me.set) },
710 name: me.name,
711 }
712 }
713
714 pub fn on_drop_fn<F>(self, hook: F) -> ComponentInfoRef<'a, T, F, S>
719 where
720 F: Fn(&mut T, EntityId, LocalActionEncoder) + Send + Sync + 'static,
721 {
722 self.on_drop(hook)
723 }
724
725 pub fn on_replace<F>(self, hook: F) -> ComponentInfoRef<'a, T, D, F>
730 where
731 F: SetHook<T>,
732 {
733 let me = ManuallyDrop::new(self);
734
735 ComponentInfoRef {
736 info: unsafe { ptr::read(&me.info) },
737 phantom: me.phantom,
738 drop: unsafe { ptr::read(&me.drop) },
739 set: ManuallyDrop::new(hook),
740 name: me.name,
741 }
742 }
743
744 pub fn on_replace_fn<F>(self, hook: F) -> ComponentInfoRef<'a, T, D, F>
749 where
750 F: Fn(&mut T, &T, EntityId, LocalActionEncoder) -> bool + Send + Sync + 'static,
751 {
752 self.on_replace(hook)
753 }
754
755 pub fn name(mut self, name: &'static str) -> Self {
757 self.name = Some(name);
758 self
759 }
760}
761
762pub(crate) struct ComponentRegistry {
764 components: HashMap<TypeId, ComponentInfo, NoOpHasherBuilder>,
765}
766
767impl ComponentRegistry {
768 pub const fn new() -> Self {
769 Self {
770 components: HashMap::with_hasher(NoOpHasherBuilder),
771 }
772 }
773
774 pub fn get_or_register<T>(&mut self) -> &ComponentInfo
775 where
776 T: Component,
777 {
778 self.components
779 .entry(type_id::<T>())
780 .or_insert_with(ComponentInfo::of::<T>)
781 }
782
783 pub fn get_or_register_raw(&mut self, info: ComponentInfo) -> &ComponentInfo {
784 self.components.entry(info.id()).or_insert(info)
785 }
786
787 pub fn register_raw(&mut self, info: ComponentInfo) {
788 match self.components.entry(info.id()) {
789 Entry::Occupied(_) => panic!("Component already registered"),
790 Entry::Vacant(e) => {
791 e.insert(info);
792 }
793 }
794 }
795
796 pub fn ensure_component_registered<T>(&mut self)
797 where
798 T: Component,
799 {
800 self.get_or_register_raw(ComponentInfo::of::<T>());
801 }
802
803 pub fn ensure_external_registered<T>(&mut self)
804 where
805 T: 'static,
806 {
807 self.get_or_register_raw(ComponentInfo::external::<T>());
808 }
809
810 pub fn register_component<'a, T>(&'a mut self) -> ComponentInfoRef<'a, T>
811 where
812 T: Component,
813 {
814 let info = match self.components.entry(type_id::<T>()) {
815 Entry::Occupied(_) => panic!("Component already registered"),
816 Entry::Vacant(e) => e.insert(ComponentInfo::of::<T>()),
817 };
818
819 ComponentInfoRef {
820 info: Some(info),
821 phantom: PhantomData,
822 drop: ManuallyDrop::new(DefaultDropHook),
823 set: ManuallyDrop::new(DefaultSetHook),
824 name: None,
825 }
826 }
827
828 pub fn register_external<'a, T>(
829 &'a mut self,
830 ) -> ComponentInfoRef<'a, T, ExternalDropHook, ExternalSetHook>
831 where
832 T: 'static,
833 {
834 let info = match self.components.entry(type_id::<T>()) {
835 Entry::Occupied(_) => panic!("Component already registered"),
836 Entry::Vacant(e) => e.insert(ComponentInfo::external::<T>()),
837 };
838
839 ComponentInfoRef {
840 info: Some(info),
841 phantom: PhantomData,
842 drop: ManuallyDrop::new(ExternalDropHook),
843 set: ManuallyDrop::new(ExternalSetHook),
844 name: None,
845 }
846 }
847
848 pub fn get_info(&self, ty: TypeId) -> Option<&ComponentInfo> {
849 self.components.get(&ty)
850 }
851
852 pub fn iter_info(&self) -> impl Iterator<Item = &ComponentInfo> {
853 self.components.values()
854 }
855}
856
857struct Opaque;
858
859type DropOneFn = unsafe fn(NonNull<Opaque>, NonNull<u8>, EntityId, LocalActionEncoder);
860type SetOneFn = unsafe fn(
861 NonNull<Opaque>,
862 NonNull<Opaque>,
863 NonNull<u8>,
864 NonNull<u8>,
865 EntityId,
866 LocalActionEncoder,
867);
868type FinalDrop = unsafe fn(NonNull<u8>, usize);
869
870unsafe fn drop_one<T, D>(
871 hook: NonNull<Opaque>,
872 ptr: NonNull<u8>,
873 id: EntityId,
874 encoder: LocalActionEncoder,
875) where
876 T: 'static,
877 D: DropHook<T>,
878{
879 let mut ptr = ptr.cast::<T>();
880 let hook = unsafe { hook.cast::<D>().as_ref() };
881 let value = unsafe { ptr.as_mut() };
882 hook.on_drop(value, id, encoder);
883 unsafe {
884 drop_in_place(value);
885 }
886}
887
888unsafe fn set_one<T, S, D>(
889 on_replace: NonNull<Opaque>,
890 on_drop: NonNull<Opaque>,
891 dst: NonNull<u8>,
892 src: NonNull<u8>,
893 id: EntityId,
894 mut encoder: LocalActionEncoder,
895) where
896 T: 'static,
897 S: SetHook<T>,
898 D: DropHook<T>,
899{
900 let src = unsafe { src.cast::<T>().as_ref() };
901 let dst = unsafe { dst.cast::<T>().as_mut() };
902 let on_replace = unsafe { on_replace.cast::<S>().as_ref() };
903 if on_replace.on_replace(dst, src, id, encoder.reborrow()) {
904 let on_drop = unsafe { on_drop.cast::<D>().as_ref() };
905 on_drop.on_drop(dst, id, encoder);
906 }
907 unsafe {
908 *dst = ptr::read(src);
909 }
910}
911
912unsafe fn final_drop<T>(ptr: NonNull<u8>, count: usize) {
915 let slice = slice_from_raw_parts_mut(ptr.cast::<T>().as_ptr(), count);
916 unsafe {
917 drop_in_place(slice);
918 }
919}
920
921pub trait Value: 'static {
923 fn name(&self) -> &'static str;
925}
926
927impl<T> Value for T
928where
929 T: Component,
930{
931 #[inline(always)]
932 fn name(&self) -> &'static str {
933 T::name()
934 }
935}