1use std::{
2 ptr::NonNull,
3 sync::{
4 Arc,
5 atomic::{AtomicUsize, Ordering},
6 },
7};
8
9use crate::extractor::Extractor;
10
11#[derive(Hash, Eq, PartialEq, Debug, Clone, Copy)]
13pub struct EntityId {
14 pub(crate) id: u32,
15}
16
17impl EntityId {
18 pub(crate) fn new(id: u32) -> Self {
19 Self { id }
20 }
21
22 pub fn from_raw(id: u32) -> Self {
28 Self { id }
29 }
30}
31
32impl std::fmt::Display for EntityId {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(f, "Entity({})", self.id)
35 }
36}
37
38#[repr(C)]
43pub(crate) struct EntityDataInner {
44 pub(crate) counter: AtomicUsize,
46
47 pub(crate) data: NonNull<u8>,
49
50 pub(crate) extractor: Arc<Extractor>,
52}
53
54pub struct EntityData {
55 inner: NonNull<EntityDataInner>,
56}
57
58unsafe impl Send for EntityData {}
61unsafe impl Sync for EntityData {}
64
65impl EntityData {
66 pub(crate) fn inner(&self) -> &EntityDataInner {
67 unsafe { self.inner.as_ref() }
70 }
71
72 pub(crate) fn new<E: crate::Extractable>(entity: E, extractor: Arc<Extractor>) -> Self {
73 let ptr = Box::into_raw(Box::new(entity)) as *mut u8;
74 let inner = EntityDataInner {
75 counter: AtomicUsize::new(1),
76 data: unsafe { NonNull::new_unchecked(ptr) },
78 extractor,
79 };
80 Self {
81 inner: unsafe { NonNull::new_unchecked(Box::into_raw(Box::new(inner))) },
83 }
84 }
85
86 pub(crate) unsafe fn extract_by_offset<T: 'static>(
87 &self,
88 offset: usize,
89 ) -> crate::Acquirable<T> {
90 let data_ptr = self.inner().data;
91 let extracted = unsafe { data_ptr.add(offset).cast::<T>() };
94 crate::Acquirable::new(extracted, self.clone())
95 }
96
97 pub(crate) fn data_ptr(&self) -> NonNull<u8> {
98 self.inner().data
99 }
100
101 pub(crate) fn extract<T: 'static>(&self) -> Option<crate::Acquirable<T>> {
102 let extracted = unsafe { self.extract_ptr::<T>()? };
104 Some(crate::Acquirable::new(extracted, self.clone()))
105 }
106
107 pub(crate) unsafe fn extract_ptr<T: 'static>(&self) -> Option<NonNull<T>> {
108 unsafe { self.inner().extractor.extract_ptr::<T>(self.inner().data) }
111 }
112}
113
114impl Drop for EntityData {
115 fn drop(&mut self) {
116 let inner = self.inner();
117 if inner.counter.fetch_sub(1, Ordering::Release) > 1 {
118 return;
119 }
120
121 std::sync::atomic::fence(Ordering::Acquire);
122
123 unsafe { (inner.extractor.dropper)(inner.data) };
127
128 unsafe {
131 let inner = Box::from_raw(self.inner.as_ptr());
132 drop(inner);
133 }
134 }
135}
136
137impl Clone for EntityData {
138 fn clone(&self) -> Self {
139 self.inner().counter.fetch_add(1, Ordering::Relaxed);
140
141 Self { inner: self.inner }
142 }
143}