1use {
7 core::{
8 cell::UnsafeCell,
9 fmt,
10 hash::Hash,
11 marker::PhantomData,
12 mem::{self, MaybeUninit},
13 ops,
14 ptr,
15 },
16 std::hash::Hasher,
17};
18
19pub const CAPACITY: usize = 4096;
20
21type Slot<T> = UnsafeCell<MaybeUninit<T>>;
22type Row<T> = [Slot<T>; CAPACITY];
23
24#[derive(Debug)]
26pub struct Arena<T> {
27 init: Vec<bool>,
33
34 rows: Vec<Box<Row<T>>>,
36}
37
38impl<T> Arena<T> {
39 #[must_use]
41 pub const fn new() -> Self {
42 Self { init: vec![], rows: vec![], }
43 }
44
45 fn clean_trailing(&mut self) {
47 let dead_elements = self
48 .init
49 .iter()
50 .rev()
51 .position(|is_init| *is_init)
52 .unwrap_or(self.init.len());
53 self
54 .init
55 .truncate(self.init.len() - dead_elements);
56 }
57
58 fn slot(&self, idx: usize) -> *mut MaybeUninit<T> {
60 debug_assert!(self.init[idx]);
61
62 let row = &self.rows[idx / CAPACITY];
63 row[idx % CAPACITY].get()
64 }
65
66 unsafe fn take_slot(&mut self, idx: usize) -> T {
71 let slot = self.slot(idx);
72 self.init[idx] = false;
73
74 unsafe {
76 ptr::read(slot).assume_init()
77 }
78 }
79}
80
81impl<T> !Send for Arena<T> {}
82impl<T> !Sync for Arena<T> {}
83
84impl<T> Default for Arena<T> {
85 fn default() -> Self {
86 Self::new()
87 }
88}
89
90pub struct ArenaIdx<T: ArenaData> {
92 inner: u32,
93 phantom: PhantomData<T>,
94}
95
96impl<T: ArenaData> ArenaIdx<T> {
97 pub fn new(value: T) -> Self {
99 T::with_arena(|arena| {
100 let arena = unsafe {
102 arena.as_mut_unchecked()
103 };
104
105 arena.clean_trailing();
107
108 let idx = arena.init.len();
110 let row = match arena.rows.get(idx / CAPACITY) {
111 Some(row) => row,
112 None => {
116 let row = unsafe {
118 Box::<[Slot<T>; CAPACITY]>::new_uninit()
119 .assume_init()
120 };
121 arena.rows.push_mut(row)
122 },
123 };
124 let slot = &row[idx % CAPACITY];
125
126 unsafe {
130 slot.as_mut_unchecked().write(value)
131 };
132 arena.init.push(true);
133
134 Self {
135 inner: idx.try_into().expect("Too many indices"),
136 phantom: PhantomData,
137 }
138 })
139 }
140
141 #[must_use = "If you don't need the value, just drop `self`"]
143 pub fn take(self) -> T {
144 let idx = self.inner as usize;
145 mem::forget(self);
146
147 T::with_arena(|arena| {
148 let arena = unsafe {
150 arena.as_mut_unchecked()
151 };
152
153 unsafe {
155 arena.take_slot(idx)
156 }
157 })
158 }
159
160 pub fn try_take_map<F, R>(self, f: F) -> Result<R, Self>
162 where
163 F: FnOnce(T) -> Result<R, T>,
164 {
165 match f(self.take()) {
167 Ok(value) => Ok(value),
168 Err(value) => Err(Self::new(value)),
169 }
170 }
171
172 #[must_use]
174 pub const fn id(&self) -> u32 {
175 self.inner
176 }
177}
178
179impl<T: ArenaData> !Send for ArenaIdx<T> {}
180impl<T: ArenaData> !Sync for ArenaIdx<T> {}
181
182impl<T: ArenaData + Clone> Clone for ArenaIdx<T> {
184 fn clone(&self) -> Self {
185 Self::new((**self).clone())
186 }
187}
188impl<T: ArenaData> ops::Deref for ArenaIdx<T> {
189 type Target = T;
190
191 fn deref(&self) -> &Self::Target {
192 let idx = self.inner as usize;
193
194 T::with_arena(|arena| {
195 let arena = unsafe {
197 arena.as_ref_unchecked()
198 };
199
200 let slot = arena.slot(idx);
201
202 unsafe {
204 MaybeUninit::assume_init_ref(&*slot)
205 }
206 })
207 }
208}
209
210impl<T: ArenaData> ops::DerefMut for ArenaIdx<T> {
211 fn deref_mut(&mut self) -> &mut Self::Target {
212 let idx = self.inner as usize;
213
214 T::with_arena(|arena| {
215 let arena = unsafe {
217 arena.as_ref_unchecked()
218 };
219
220 let slot = arena.slot(idx);
221
222 unsafe {
224 MaybeUninit::assume_init_mut(&mut *slot)
225 }
226 })
227 }
228}
229
230impl<T: ArenaData> Drop for ArenaIdx<T> {
231 fn drop(&mut self) {
232 let idx = self.inner as usize;
233
234 T::with_arena(|arena| {
235 let arena = unsafe {
237 arena.as_mut_unchecked()
238 };
239
240 let _ = unsafe {
243 arena.take_slot(idx)
244 };
245 });
246 }
247}
248
249impl<T: ArenaData + PartialEq> PartialEq for ArenaIdx<T> {
250 fn eq(&self, other: &Self) -> bool {
251 if self.inner == other.inner {
252 return true;
253 }
254
255 (**self) == (**other)
256 }
257}
258
259impl<T: ArenaData + Eq> Eq for ArenaIdx<T> {}
260
261impl<T: ArenaData> Hash for ArenaIdx<T> {
262 fn hash<H: Hasher>(&self, state: &mut H) {
263 self.inner.hash(state);
264 }
265}
266
267impl<T: ArenaData + fmt::Debug> fmt::Debug for ArenaIdx<T> {
268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 f
270 .debug_struct("ArenaIdx")
271 .field("idx", &self.inner)
272 .field("inner", &**self).finish()
273 }
274}
275
276
277impl<T: ArenaData + serde::Serialize> serde::Serialize for ArenaIdx<T> {
278 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
279 where
280 S: serde::Serializer,
281 {
282 (**self).serialize(serializer)
283 }
284}
285
286impl<'de, T: ArenaData + serde::Deserialize<'de>> serde::Deserialize<'de> for ArenaIdx<T> {
287 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
288 where
289 D: serde::Deserializer<'de>,
290 {
291 let value = T::deserialize(deserializer)?;
292 Ok(Self::new(value))
293 }
294}
295
296pub trait ArenaData: Sized + 'static {
298 fn with_arena<O>(f: impl FnOnce(&UnsafeCell<Arena<Self>>) -> O) -> O;
299}
300
301pub macro decl_arena(
303 $Ty:ty
304) {
305 impl ArenaData for $Ty {
306 fn with_arena<O>(f: impl FnOnce(&UnsafeCell<Arena<Self>>) -> O) -> O {
307 f(&ARENA)
308 }
309 }
310
311 #[thread_local]
312 static ARENA: UnsafeCell<Arena<$Ty>> = UnsafeCell::new(Arena::new());
313}
314
315pub macro ArenaData {
318 derive() ($( #[$meta:meta] )* $vis:vis struct $Ty:ident $($rest:tt)*) => {
319 decl_arena! { $Ty }
320 },
321
322 derive() ($( #[$meta:meta] )* $vis:vis enum $Ty:ident $($rest:tt)*) => {
323 decl_arena! { $Ty }
324 }
325}