1use intuicio_data::{
2 Finalize,
3 lifetime::{Lifetime, ReadLock, ValueReadAccess, ValueWriteAccess},
4 type_hash::TypeHash,
5};
6use serde::{Deserialize, Serialize};
7use std::{
8 alloc::{Layout, alloc, dealloc},
9 error::Error,
10 marker::PhantomData,
11};
12
13#[derive(Debug, PartialEq, Eq)]
14pub enum ArenaError {
15 InvalidAreaType { type_hash: TypeHash },
16 IndexNotFound { type_hash: TypeHash, index: Index },
17 CannotReadItem { type_hash: TypeHash, index: Index },
18 CannotWriteItem { type_hash: TypeHash, index: Index },
19 ArenaNotFound { type_hash: TypeHash },
20}
21
22impl Error for ArenaError {}
23
24impl std::fmt::Display for ArenaError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::InvalidAreaType { type_hash } => {
28 write!(f, "Invalid area type: {:?}", type_hash)
29 }
30 Self::IndexNotFound { type_hash, index } => {
31 write!(f, "Index: {} not found in arena: {:?}", index, type_hash)
32 }
33 Self::CannotReadItem { type_hash, index } => {
34 write!(
35 f,
36 "Cannot read item at index: {} in arena: {:?}",
37 index, type_hash
38 )
39 }
40 Self::CannotWriteItem { type_hash, index } => {
41 write!(
42 f,
43 "Cannot write item at index: {} in arena: {:?}",
44 index, type_hash
45 )
46 }
47 Self::ArenaNotFound { type_hash } => {
48 write!(f, "Arena not found: {:?}", type_hash)
49 }
50 }
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
55pub struct Index {
56 id: u32,
57 generation: u32,
58}
59
60impl Default for Index {
61 fn default() -> Self {
62 Self::INVALID
63 }
64}
65
66impl Index {
67 pub const INVALID: Self = unsafe { Self::new_unchecked(u32::MAX, 0) };
68
69 pub const fn new(id: u32, generation: u32) -> Option<Self> {
70 if id < u32::MAX {
71 Some(Self { id, generation })
72 } else {
73 None
74 }
75 }
76
77 pub const unsafe fn new_unchecked(id: u32, generation: u32) -> Self {
79 Self { id, generation }
80 }
81
82 pub const fn is_valid(self) -> bool {
83 self.id < u32::MAX
84 }
85
86 pub const fn id(self) -> u32 {
87 self.id
88 }
89
90 pub const fn generation(self) -> u32 {
91 self.generation
92 }
93
94 pub const fn to_u64(self) -> u64 {
95 ((self.generation as u64) << 32) | self.id as u64
96 }
97
98 pub const fn from_u64(value: u64) -> Self {
99 Self {
100 generation: (value >> 32) as u32,
101 id: value as u32,
102 }
103 }
104
105 pub const fn bump_generation(mut self) -> Self {
106 self.generation = self.generation.wrapping_add(1);
107 self
108 }
109}
110
111impl std::fmt::Display for Index {
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 if self.is_valid() {
114 write!(f, "@{}:#{}", self.id, self.generation)
115 } else {
116 write!(f, "@none:#{}", self.generation)
117 }
118 }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
122pub struct AnyIndex {
123 index: Index,
124 type_hash: TypeHash,
125}
126
127impl Default for AnyIndex {
128 fn default() -> Self {
129 Self::INVALID
130 }
131}
132
133impl AnyIndex {
134 pub const INVALID: Self = Self::new(Index::INVALID, TypeHash::INVALID);
135
136 pub const fn new(index: Index, type_hash: TypeHash) -> Self {
137 Self { index, type_hash }
138 }
139
140 pub fn is<T>(self) -> bool {
141 self.type_hash == TypeHash::of::<T>()
142 }
143
144 pub const fn is_valid(self) -> bool {
145 self.index.is_valid()
146 }
147
148 pub const fn index(self) -> Index {
149 self.index
150 }
151
152 pub const fn type_hash(self) -> TypeHash {
153 self.type_hash
154 }
155}
156
157impl std::fmt::Display for AnyIndex {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 write!(f, "{}:^{}", self.index, self.type_hash)
160 }
161}
162
163pub struct Arena {
164 type_hash: TypeHash,
165 item_layout: Layout,
166 finalizer: unsafe fn(*mut ()),
167 memory: *mut u8,
168 capacity: usize,
169 layout: Layout,
170 lifetime: Lifetime,
171 indices_lifetimes: Vec<(Index, Lifetime)>,
172 indices_to_reuse: Vec<Index>,
173 index_generator: u32,
174}
175
176unsafe impl Send for Arena {}
177unsafe impl Sync for Arena {}
178
179impl Drop for Arena {
180 fn drop(&mut self) {
181 self.clear();
182 self.lifetime.write_lock().using(|| unsafe {
183 dealloc(self.memory, self.layout);
184 });
185 }
186}
187
188impl Arena {
189 pub fn new<T: Finalize>(capacity: usize) -> Self {
190 unsafe {
191 Self::new_raw(
192 TypeHash::of::<T>(),
193 Layout::new::<T>(),
194 T::finalize_raw,
195 capacity,
196 )
197 }
198 }
199
200 pub unsafe fn new_raw(
202 type_hash: TypeHash,
203 mut item_layout: Layout,
204 finalizer: unsafe fn(*mut ()),
205 mut capacity: usize,
206 ) -> Self {
207 item_layout = item_layout.pad_to_align();
208 capacity = capacity.max(1);
209 let (memory, layout) = unsafe { Self::allocate_memory_unlocked(item_layout, capacity) };
210 Self {
211 type_hash,
212 item_layout,
213 finalizer,
214 memory,
215 capacity,
216 layout,
217 lifetime: Default::default(),
218 indices_lifetimes: Vec::with_capacity(capacity),
219 indices_to_reuse: Default::default(),
220 index_generator: 0,
221 }
222 }
223
224 pub fn type_hash(&self) -> TypeHash {
225 self.type_hash
226 }
227
228 pub fn item_layout(&self) -> &Layout {
229 &self.item_layout
230 }
231
232 pub fn finalizer(&self) -> unsafe fn(*mut ()) {
233 self.finalizer
234 }
235
236 pub fn capacity(&self) -> usize {
237 self.lifetime.read_lock().using(|| self.capacity)
238 }
239
240 pub fn len(&self) -> usize {
241 self.lifetime
242 .read_lock()
243 .using(|| self.indices_lifetimes.len())
244 }
245
246 pub fn is_empty(&self) -> bool {
247 self.lifetime
248 .read_lock()
249 .using(|| self.indices_lifetimes.is_empty())
250 }
251
252 pub fn contains(&self, index: Index) -> bool {
253 self.lifetime
254 .read_lock()
255 .using(|| self.indices_lifetimes.iter().any(|(idx, _)| *idx == index))
256 }
257
258 pub fn clear(&mut self) {
259 self.lifetime.write_lock().using(|| {
260 for index in 0..self.indices_lifetimes.len() {
261 unsafe {
262 let target = self.memory.add(index * self.item_layout.size());
263 (self.finalizer)(target.cast());
264 }
265 }
266 self.indices_lifetimes.clear();
267 });
268 }
269
270 pub fn insert<T>(&mut self, value: T) -> Result<Index, ArenaError> {
271 self.lifetime.write_lock().using(move || unsafe {
272 let type_hash = TypeHash::of::<T>();
273 if self.type_hash == type_hash {
274 let (index, target) = self.allocate_unlocked();
275 target.cast::<T>().write(value);
276 Ok(index)
277 } else {
278 Err(ArenaError::InvalidAreaType { type_hash })
279 }
280 })
281 }
282
283 pub unsafe fn allocate(&mut self) -> (Index, *mut u8) {
285 self.lifetime
286 .write_lock()
287 .using(|| unsafe { self.allocate_unlocked() })
288 }
289
290 pub fn remove(&mut self, index: Index) -> Result<(), ArenaError> {
291 self.lifetime.write_lock().using(|| {
292 if self.indices_lifetimes.is_empty() {
293 return Err(ArenaError::IndexNotFound {
294 type_hash: self.type_hash,
295 index,
296 });
297 }
298 let Some(idx) = self
299 .indices_lifetimes
300 .iter()
301 .position(|(idx, _)| *idx == index)
302 else {
303 return Err(ArenaError::IndexNotFound {
304 type_hash: self.type_hash,
305 index,
306 });
307 };
308 self.indices_to_reuse.push(index);
309 unsafe {
310 let target = self.memory.add(idx * self.item_layout.size());
311 (self.finalizer)(target.cast());
312 self.indices_lifetimes.swap_remove(idx);
313 if self.indices_lifetimes.len() != idx {
314 let source = self
315 .memory
316 .add(self.indices_lifetimes.len() * self.item_layout.size());
317 source.copy_to(target, self.item_layout.size());
318 self.indices_lifetimes[idx].1 = Default::default();
319 }
320 }
321 Ok(())
322 })
323 }
324
325 pub fn read<T>(&self, index: Index) -> Result<ValueReadAccess<T>, ArenaError> {
326 self.lifetime.read_lock().using(|| unsafe {
327 let type_hash = TypeHash::of::<T>();
328 if self.type_hash != type_hash {
329 return Err(ArenaError::InvalidAreaType { type_hash });
330 }
331 if let Some(idx) = self
332 .indices_lifetimes
333 .iter()
334 .position(|(idx, _)| *idx == index)
335 {
336 let address = self
337 .memory
338 .cast_const()
339 .add(idx * self.item_layout.size())
340 .cast::<T>();
341 self.indices_lifetimes[idx]
342 .1
343 .read_ptr(address)
344 .ok_or(ArenaError::CannotReadItem {
345 type_hash: self.type_hash,
346 index,
347 })
348 } else {
349 Err(ArenaError::IndexNotFound {
350 type_hash: self.type_hash,
351 index,
352 })
353 }
354 })
355 }
356
357 pub fn write<T>(&self, index: Index) -> Result<ValueWriteAccess<T>, ArenaError> {
358 self.lifetime.read_lock().using(|| unsafe {
359 let type_hash = TypeHash::of::<T>();
360 if self.type_hash != type_hash {
361 return Err(ArenaError::InvalidAreaType { type_hash });
362 }
363 if let Some(idx) = self
364 .indices_lifetimes
365 .iter()
366 .position(|(idx, _)| *idx == index)
367 {
368 let address = self.memory.add(idx * self.item_layout.size()).cast::<T>();
369 self.indices_lifetimes[idx].1.write_ptr(address).ok_or(
370 ArenaError::CannotWriteItem {
371 type_hash: self.type_hash,
372 index,
373 },
374 )
375 } else {
376 Err(ArenaError::IndexNotFound {
377 type_hash: self.type_hash,
378 index,
379 })
380 }
381 })
382 }
383
384 pub unsafe fn read_ptr(&self, index: Index) -> Result<*const u8, ArenaError> {
386 self.lifetime.read_lock().using(|| unsafe {
387 if let Some(idx) = self
388 .indices_lifetimes
389 .iter()
390 .position(|(idx, _)| *idx == index)
391 {
392 Ok(self.memory.cast_const().add(idx * self.item_layout.size()))
393 } else {
394 Err(ArenaError::IndexNotFound {
395 type_hash: self.type_hash,
396 index,
397 })
398 }
399 })
400 }
401
402 pub unsafe fn write_ptr(&self, index: Index) -> Result<*mut u8, ArenaError> {
404 self.lifetime.read_lock().using(|| unsafe {
405 if let Some(idx) = self
406 .indices_lifetimes
407 .iter()
408 .position(|(idx, _)| *idx == index)
409 {
410 Ok(self.memory.add(idx * self.item_layout.size()))
411 } else {
412 Err(ArenaError::IndexNotFound {
413 type_hash: self.type_hash,
414 index,
415 })
416 }
417 })
418 }
419
420 pub fn is<T>(&self, index: Index) -> Result<bool, ArenaError> {
421 self.is_raw(index, TypeHash::of::<T>())
422 }
423
424 pub fn is_raw(&self, index: Index, type_hash: TypeHash) -> Result<bool, ArenaError> {
425 self.lifetime.read_lock().using(|| {
426 if self.type_hash == type_hash {
427 Ok(self.indices_lifetimes.iter().any(|(idx, _)| *idx == index))
428 } else {
429 Err(ArenaError::InvalidAreaType { type_hash })
430 }
431 })
432 }
433
434 pub fn indices(&self) -> impl Iterator<Item = Index> + '_ {
435 let _lock = self.lifetime.read_lock();
436 ArenaLockedIter {
437 inner: self.indices_lifetimes.iter().map(|(index, _)| *index),
438 _lock,
439 }
440 }
441
442 pub fn iter<'a, T: 'a>(&'a self) -> impl Iterator<Item = ValueReadAccess<'a, T>> {
443 let type_hash = TypeHash::of::<T>();
444 (self.type_hash == type_hash)
445 .then_some(())
446 .into_iter()
447 .flat_map(|_| {
448 let _lock = self.lifetime.read_lock();
449 ArenaLockedIter {
450 inner: ArenaIter {
451 arena: self,
452 index: 0,
453 _phantom: PhantomData,
454 },
455 _lock,
456 }
457 })
458 }
459
460 pub fn iter_mut<'a, T: 'a>(&'a self) -> impl Iterator<Item = ValueWriteAccess<'a, T>> {
461 let type_hash = TypeHash::of::<T>();
462 (self.type_hash == type_hash)
463 .then_some(())
464 .into_iter()
465 .flat_map(|_| {
466 let _lock = self.lifetime.read_lock();
467 ArenaLockedIter {
468 inner: ArenaIterMut {
469 arena: self,
470 index: 0,
471 _phantom: PhantomData,
472 },
473 _lock,
474 }
475 })
476 }
477
478 unsafe fn allocate_unlocked(&mut self) -> (Index, *mut u8) {
480 if self.indices_lifetimes.len() == self.capacity {
481 self.capacity *= 2;
482 unsafe { self.reallocate_unlocked(self.indices_lifetimes.len(), self.capacity) };
483 }
484 let index = match self.indices_to_reuse.pop() {
485 Some(index) => index.bump_generation(),
486 None => {
487 let id = self.index_generator;
488 self.index_generator = self.index_generator.wrapping_add(1);
489 unsafe { Index::new_unchecked(id, 0) }
490 }
491 };
492 let idx = self.indices_lifetimes.len();
493 self.indices_lifetimes.push((index, Default::default()));
494 (index, unsafe {
495 self.memory.add(idx * self.item_layout.size())
496 })
497 }
498
499 unsafe fn reallocate_unlocked(&mut self, size: usize, capacity: usize) {
500 let (memory, layout) =
501 unsafe { Self::allocate_memory_unlocked(self.item_layout, capacity) };
502 unsafe { self.memory.copy_to(memory, self.item_layout.size() * size) };
503 unsafe { dealloc(self.memory, self.layout) };
504 self.memory = memory;
505 self.layout = layout;
506 for (_, lifetime) in &mut self.indices_lifetimes {
507 *lifetime = Default::default();
508 }
509 }
510
511 unsafe fn allocate_memory_unlocked(
512 mut item_layout: Layout,
513 capacity: usize,
514 ) -> (*mut u8, Layout) {
515 item_layout = item_layout.pad_to_align();
516 let layout = if item_layout.size() == 0 {
517 unsafe { Layout::from_size_align_unchecked(1, 1) }
518 } else {
519 unsafe {
520 Layout::from_size_align_unchecked(
521 item_layout.size() * capacity,
522 item_layout.align(),
523 )
524 }
525 };
526 let memory = unsafe { alloc(layout) };
527 (memory, layout)
528 }
529}
530
531#[derive(Default)]
532pub struct AnyArena {
533 pub new_arena_capacity: usize,
534 arenas: Vec<Arena>,
535}
536
537impl AnyArena {
538 pub fn with_new_arena_capacity(mut self, capacity: usize) -> Self {
539 self.new_arena_capacity = capacity;
540 self
541 }
542
543 pub fn len(&self) -> usize {
544 self.arenas.iter().map(|arena| arena.len()).sum()
545 }
546
547 pub fn is_empty(&self) -> bool {
548 self.arenas.iter().all(|arena| arena.is_empty())
549 }
550
551 pub fn contains(&self, index: AnyIndex) -> bool {
552 self.arenas
553 .iter()
554 .find(|arena| arena.type_hash == index.type_hash)
555 .map(|arena| arena.contains(index.index))
556 .unwrap_or_default()
557 }
558
559 pub fn arenas(&self) -> &[Arena] {
560 &self.arenas
561 }
562
563 pub fn arenas_mut(&mut self) -> &mut [Arena] {
564 &mut self.arenas
565 }
566
567 pub fn arena<T>(&self) -> Option<&Arena> {
568 unsafe { self.arena_raw(TypeHash::of::<T>()) }
569 }
570
571 pub unsafe fn arena_raw(&self, type_hash: TypeHash) -> Option<&Arena> {
573 self.arenas
574 .iter()
575 .find(|arena| arena.type_hash == type_hash)
576 }
577
578 pub fn ensure_arena<T: Finalize>(&mut self) -> &mut Arena {
579 unsafe {
580 self.ensure_arena_raw(
581 TypeHash::of::<T>(),
582 Layout::new::<T>().pad_to_align(),
583 T::finalize_raw,
584 )
585 }
586 }
587
588 pub unsafe fn ensure_arena_raw(
590 &mut self,
591 type_hash: TypeHash,
592 item_layout: Layout,
593 finalizer: unsafe fn(*mut ()),
594 ) -> &mut Arena {
595 let index = match self
596 .arenas
597 .iter()
598 .position(|arena| arena.type_hash == type_hash)
599 {
600 Some(index) => index,
601 None => {
602 self.arenas.push(unsafe {
603 Arena::new_raw(type_hash, item_layout, finalizer, self.new_arena_capacity)
604 });
605 self.arenas.len() - 1
606 }
607 };
608 &mut self.arenas[index]
609 }
610
611 pub fn clear(&mut self) {
612 for arena in &mut self.arenas {
613 arena.clear();
614 }
615 self.arenas.clear();
616 }
617
618 pub fn insert<T: Finalize>(&mut self, value: T) -> AnyIndex {
619 let type_hash = TypeHash::of::<T>();
620 if let Some(arena) = self
621 .arenas
622 .iter_mut()
623 .find(|arena| arena.type_hash == type_hash)
624 {
625 AnyIndex::new(arena.insert(value).unwrap(), type_hash)
626 } else {
627 let mut arena = Arena::new::<T>(self.new_arena_capacity);
628 let index = arena.insert(value).unwrap();
629 self.arenas.push(arena);
630 AnyIndex::new(index, type_hash)
631 }
632 }
633
634 pub unsafe fn allocate(
636 &mut self,
637 type_hash: TypeHash,
638 item_layout: Layout,
639 finalizer: unsafe fn(*mut ()),
640 ) -> (AnyIndex, *mut u8) {
641 if let Some(arena) = self
642 .arenas
643 .iter_mut()
644 .find(|arena| arena.type_hash == type_hash)
645 {
646 let (index, address) = unsafe { arena.allocate() };
647 (AnyIndex::new(index, type_hash), address)
648 } else {
649 let mut arena = unsafe {
650 Arena::new_raw(type_hash, item_layout, finalizer, self.new_arena_capacity)
651 };
652 let (index, address) = unsafe { arena.allocate() };
653 self.arenas.push(arena);
654 (AnyIndex::new(index, type_hash), address)
655 }
656 }
657
658 pub fn remove(&mut self, index: AnyIndex) -> Result<(), ArenaError> {
659 if let Some(idx) = self
660 .arenas
661 .iter_mut()
662 .position(|arena| arena.type_hash == index.type_hash)
663 {
664 let result = self.arenas[idx].remove(index.index);
665 if self.arenas[idx].is_empty() {
666 self.arenas.swap_remove(idx);
667 }
668 result
669 } else {
670 Err(ArenaError::ArenaNotFound {
671 type_hash: index.type_hash,
672 })
673 }
674 }
675
676 pub fn read<T>(&self, index: AnyIndex) -> Result<ValueReadAccess<T>, ArenaError> {
677 if let Some(arena) = self
678 .arenas
679 .iter()
680 .find(|arena| arena.type_hash == index.type_hash)
681 {
682 arena.read(index.index)
683 } else {
684 Err(ArenaError::ArenaNotFound {
685 type_hash: index.type_hash,
686 })
687 }
688 }
689
690 pub fn write<T>(&self, index: AnyIndex) -> Result<ValueWriteAccess<T>, ArenaError> {
691 if let Some(arena) = self
692 .arenas
693 .iter()
694 .find(|arena| arena.type_hash == index.type_hash)
695 {
696 arena.write(index.index)
697 } else {
698 Err(ArenaError::ArenaNotFound {
699 type_hash: index.type_hash,
700 })
701 }
702 }
703
704 pub unsafe fn read_ptr(&self, index: AnyIndex) -> Result<*const u8, ArenaError> {
706 if let Some(arena) = self
707 .arenas
708 .iter()
709 .find(|arena| arena.type_hash == index.type_hash)
710 {
711 unsafe { arena.read_ptr(index.index) }
712 } else {
713 Err(ArenaError::ArenaNotFound {
714 type_hash: index.type_hash,
715 })
716 }
717 }
718
719 pub unsafe fn write_ptr(&self, index: AnyIndex) -> Result<*mut u8, ArenaError> {
721 if let Some(arena) = self
722 .arenas
723 .iter()
724 .find(|arena| arena.type_hash == index.type_hash)
725 {
726 unsafe { arena.write_ptr(index.index) }
727 } else {
728 Err(ArenaError::ArenaNotFound {
729 type_hash: index.type_hash,
730 })
731 }
732 }
733
734 pub fn is<T>(&self, index: AnyIndex) -> Result<bool, ArenaError> {
735 self.is_raw(index, TypeHash::of::<T>())
736 }
737
738 pub fn is_raw(&self, index: AnyIndex, type_hash: TypeHash) -> Result<bool, ArenaError> {
739 for arena in &self.arenas {
740 if arena.type_hash == type_hash {
741 return Ok(arena.contains(index.index));
742 }
743 }
744 Err(ArenaError::ArenaNotFound {
745 type_hash: index.type_hash,
746 })
747 }
748
749 pub fn indices(&self) -> impl Iterator<Item = AnyIndex> + '_ {
750 self.arenas.iter().flat_map(|arena| {
751 arena
752 .indices()
753 .map(move |index| AnyIndex::new(index, arena.type_hash))
754 })
755 }
756
757 pub fn iter<'a, T: 'a>(&'a self) -> impl Iterator<Item = ValueReadAccess<'a, T>> {
758 self.arenas.iter().flat_map(|arena| arena.iter::<T>())
759 }
760
761 pub fn iter_mut<'a, T: 'a>(&'a self) -> impl Iterator<Item = ValueWriteAccess<'a, T>> {
762 self.arenas.iter().flat_map(|arena| arena.iter_mut::<T>())
763 }
764}
765
766pub struct ArenaLockedIter<T, I: Iterator<Item = T>> {
767 inner: I,
768 _lock: ReadLock,
769}
770
771impl<T, I: Iterator<Item = T>> Iterator for ArenaLockedIter<T, I> {
772 type Item = T;
773
774 fn next(&mut self) -> Option<Self::Item> {
775 self.inner.next()
776 }
777}
778
779pub struct ArenaIter<'a, T> {
780 index: usize,
781 arena: &'a Arena,
782 _phantom: PhantomData<fn() -> T>,
783}
784
785impl<'a, T: 'a> Iterator for ArenaIter<'a, T> {
786 type Item = ValueReadAccess<'a, T>;
787
788 fn next(&mut self) -> Option<Self::Item> {
789 if self.index < self.arena.indices_lifetimes.len() {
790 unsafe {
791 let address = self.arena.memory.cast::<T>().add(self.index);
792 let result = self.arena.indices_lifetimes[self.index]
793 .1
794 .read_ptr::<T>(address);
795 self.index += 1;
796 result
797 }
798 } else {
799 None
800 }
801 }
802
803 fn size_hint(&self) -> (usize, Option<usize>) {
804 let size = self.arena.indices_lifetimes.len() - self.index;
805 (size, Some(size))
806 }
807}
808
809pub struct ArenaIterMut<'a, T> {
810 index: usize,
811 arena: &'a Arena,
812 _phantom: PhantomData<fn() -> T>,
813}
814
815impl<'a, T: 'a> Iterator for ArenaIterMut<'a, T> {
816 type Item = ValueWriteAccess<'a, T>;
817
818 fn next(&mut self) -> Option<Self::Item> {
819 if self.index < self.arena.indices_lifetimes.len() {
820 unsafe {
821 let address = self.arena.memory.cast::<T>().add(self.index);
822 let result = self.arena.indices_lifetimes[self.index]
823 .1
824 .write_ptr::<T>(address);
825 self.index += 1;
826 result
827 }
828 } else {
829 None
830 }
831 }
832
833 fn size_hint(&self) -> (usize, Option<usize>) {
834 let size = self.arena.indices_lifetimes.len() - self.index;
835 (size, Some(size))
836 }
837}
838
839#[cfg(test)]
840mod tests {
841 use super::*;
842
843 #[test]
844 fn test_async() {
845 fn is_async<T: Send + Sync>() {}
846
847 is_async::<Arena>();
848 is_async::<AnyArena>();
849 }
850
851 #[test]
852 fn test_arena() {
853 let mut arena = Arena::new::<String>(0);
854 assert_eq!(arena.type_hash(), TypeHash::of::<String>());
855 assert!(arena.is_empty());
856 assert_eq!(arena.len(), 0);
857 assert_eq!(arena.capacity(), 1);
858
859 let hello = arena.insert("Hello".to_owned()).unwrap();
860 assert!(!arena.is_empty());
861 assert_eq!(arena.len(), 1);
862 assert_eq!(arena.capacity(), 1);
863 assert!(arena.contains(hello));
864
865 let world = arena.insert("World!".to_owned()).unwrap();
866 assert!(!arena.is_empty());
867 assert_eq!(arena.len(), 2);
868 assert_eq!(arena.capacity(), 2);
869 assert!(arena.contains(world));
870
871 assert_eq!(arena.read::<String>(hello).unwrap().as_str(), "Hello");
872 assert_eq!(arena.read::<String>(world).unwrap().as_str(), "World!");
873
874 *arena.write(world).unwrap() = "world".to_owned();
875 assert_eq!(arena.read::<String>(world).unwrap().as_str(), "world");
876
877 assert_eq!(
878 arena
879 .iter::<String>()
880 .map(|item| item.to_owned())
881 .collect::<Vec<_>>(),
882 vec!["Hello".to_owned(), "world".to_owned()]
883 );
884
885 arena.remove(hello).unwrap();
886 assert!(!arena.is_empty());
887 assert_eq!(arena.len(), 1);
888 assert_eq!(arena.capacity(), 2);
889 assert!(!arena.contains(hello));
890
891 assert!(arena.read::<String>(hello).is_err());
892 assert_eq!(arena.read::<String>(world).unwrap().as_str(), "world");
893
894 arena.clear();
895 assert!(arena.is_empty());
896 assert_eq!(arena.len(), 0);
897 assert_eq!(arena.capacity(), 2);
898 }
899
900 #[test]
901 fn test_typed_arena() {
902 let mut arena = AnyArena::default();
903 assert!(arena.is_empty());
904 assert_eq!(arena.len(), 0);
905
906 let number = arena.insert(42usize);
907 assert!(!arena.is_empty());
908 assert_eq!(arena.len(), 1);
909 assert!(arena.contains(number));
910
911 let boolean = arena.insert(true);
912 assert!(!arena.is_empty());
913 assert_eq!(arena.len(), 2);
914 assert!(arena.contains(boolean));
915
916 assert_eq!(*arena.read::<usize>(number).unwrap(), 42);
917 assert!(*arena.read::<bool>(boolean).unwrap());
918
919 *arena.write(boolean).unwrap() = false;
920 assert!(!*arena.read::<bool>(boolean).unwrap());
921
922 arena.remove(number).unwrap();
923 assert!(!arena.is_empty());
924 assert_eq!(arena.len(), 1);
925 assert!(!arena.contains(number));
926
927 assert!(arena.read::<usize>(number).is_err());
928 assert!(!*arena.read::<bool>(boolean).unwrap());
929
930 arena.clear();
931 assert!(arena.is_empty());
932 assert_eq!(arena.len(), 0);
933 }
934}