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