1#![cfg_attr(feature="nightly", feature(allocator_api))]
2#![cfg_attr(feature="nightly", feature(associated_type_defaults))]
3
4#![deny(warnings)]
5#![doc(test(attr(deny(warnings))))]
6#![doc(test(attr(allow(dead_code))))]
7#![doc(test(attr(allow(unused_variables))))]
8#![allow(unknown_lints)]
9#![allow(clippy::needless_lifetimes)]
10#![allow(clippy::non_canonical_clone_impl)]
11#![allow(clippy::non_canonical_partial_ord_impl)]
12#![allow(clippy::type_complexity)]
13
14#![doc=document_features::document_features!()]
16
17#![no_std]
18
19#[doc=include_str!("../README.md")]
20type _DocTestReadme = ();
21
22extern crate alloc as alloc_crate;
23
24#[doc(hidden)]
25pub use core::compile_error as std_compile_error;
26#[doc(hidden)]
27pub use core::concat as std_concat;
28#[doc(hidden)]
29pub use core::default::Default as std_default_Default;
30#[doc(hidden)]
31pub use core::option::Option as std_option_Option;
32#[doc(hidden)]
33pub use core::stringify as std_stringify;
34#[doc(hidden)]
35pub use generics::parse as generics_parse;
36
37#[cfg(feature="nightly")]
38use alloc_crate::alloc::Allocator;
39use alloc_crate::collections::TryReserveError;
40use alloc_crate::vec::{self, Vec};
41#[cfg(feature="nightly")]
42use composable_allocators::Global as Global;
43#[cfg(feature="nightly")]
44use const_default::ConstDefault;
45use core::fmt::Debug;
46use core::hint::unreachable_unchecked;
47use core::iter::{self, FusedIterator};
48use core::mem::{align_of, replace, size_of};
49use core::num::NonZeroUsize;
50use core::ops::{Index, IndexMut};
51use core::slice::{self};
52use core::sync::atomic::{AtomicUsize, Ordering};
53use educe::Educe;
54use either::{Either, Left, Right};
55use phantom_type::PhantomType;
56use rand::rngs::SmallRng;
57use rand::{RngCore, SeedableRng};
58
59pub use components_arena_traits::*;
60
61pub struct ComponentClassToken(AtomicUsize);
67
68impl ComponentClassToken {
69 pub const fn new() -> Self { ComponentClassToken(AtomicUsize::new(0)) }
73}
74
75impl Default for ComponentClassToken {
76 fn default() -> Self { ComponentClassToken::new() }
77}
78
79pub trait ComponentClass {
111 fn token() -> &'static ComponentClassToken where Self: Sized;
113}
114
115pub trait Component {
121 type Class: ComponentClass;
126
127 #[cfg(feature="nightly")]
132 type Alloc: Allocator = Global;
133}
134
135#[derive(Educe)]
137#[educe(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
138pub struct Id<C: Component> {
139 index: usize,
140 guard: NonZeroUsize,
141 phantom: PhantomType<C>
142}
143
144impl<C: Component> ComponentId for Id<C> {
145 fn from_raw(raw: RawId) -> Self {
146 Id { index: raw.0, guard: raw.1, phantom: PhantomType::new() }
147 }
148
149 fn into_raw(self) -> RawId {
150 (self.index, self.guard)
151 }
152}
153
154type ArenaItem<C> = Either<Option<usize>, (NonZeroUsize, C)>;
155
156#[derive(Debug, Clone)]
160pub struct ArenaItems<C: Component> {
161 #[cfg(feature="nightly")]
162 vec: Vec<ArenaItem<C>, C::Alloc>,
163
164 #[cfg(not(feature="nightly"))]
165 vec: Vec<ArenaItem<C>>,
166
167 vacancy: Option<usize>,
168}
169
170impl<C: Component> ArenaItems<C> {
171 pub const fn item_size() -> usize {
175 size_of::<ArenaItem<C>>()
176 }
177
178 pub const fn item_align() -> usize {
182 align_of::<ArenaItem<C>>()
183 }
184
185 #[cfg(feature="nightly")]
186 const fn new_in(alloc: C::Alloc) -> Self {
187 ArenaItems {
188 vec: Vec::new_in(alloc),
189 vacancy: None
190 }
191 }
192
193 #[cfg(not(feature="nightly"))]
194 const fn new() -> Self {
195 ArenaItems {
196 vec: Vec::new(),
197 vacancy: None
198 }
199 }
200
201 #[cfg(feature="nightly")]
202 fn with_capacity_in(capacity: usize, alloc: C::Alloc) -> Self {
203 ArenaItems {
204 vec: Vec::with_capacity_in(capacity, alloc),
205 vacancy: None
206 }
207 }
208
209 #[cfg(not(feature="nightly"))]
210 fn with_capacity(capacity: usize) -> Self {
211 ArenaItems {
212 vec: Vec::with_capacity(capacity),
213 vacancy: None
214 }
215 }
216
217 #[cfg(feature="nightly")]
219 pub fn allocator(&self) -> &C::Alloc { self.vec.allocator() }
220
221 pub fn capacity(&self) -> usize { self.vec.capacity() }
223
224 pub fn len(&self) -> usize {
228 let mut vacancies = 0;
229 let mut vacancy = self.vacancy;
230 while let Some(i) = vacancy {
231 vacancies += 1;
232 vacancy = *self.vec[i].as_ref().left().unwrap();
233 }
234 self.vec.len() - vacancies
235 }
236
237 pub fn len_equals_to_min_capacity(&self) -> bool {
245 self.vacancy.is_none()
246 }
247
248 pub fn is_empty(&self) -> bool { self.vec.iter().all(|x| x.is_left()) }
252
253 pub fn min_capacity(&self) -> usize { self.vec.len() }
285
286 pub fn reserve(&mut self, additional: usize) { self.vec.reserve(additional) }
295
296 pub fn reserve_exact(&mut self, additional: usize) { self.vec.reserve_exact(additional) }
308
309 pub fn shrink_to(&mut self, min_capacity: usize) { self.vec.shrink_to(min_capacity) }
314
315 pub fn shrink_to_fit(&mut self) { self.vec.shrink_to_fit() }
320
321 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
330 self.vec.try_reserve(additional)
331 }
332
333 pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
346 self.vec.try_reserve_exact(additional)
347 }
348
349 pub fn get_id_value(&self, index: usize) -> Option<(Id<C>, &C)> {
355 self.vec[index].as_ref().right().map(|(guard, item)| (Id { index, guard: *guard, phantom: PhantomType::new() }, item))
356 }
357
358 pub fn get_id_value_mut(&mut self, index: usize) -> Option<(Id<C>, &mut C)> {
364 self.vec[index].as_mut().right().map(|(guard, item)| (Id { index, guard: *guard, phantom: PhantomType::new() }, item))
365 }
366
367 pub fn get_id(&self, index: usize) -> Option<Id<C>> {
373 self.vec[index].as_ref().right().map(|(guard, _)| Id { index, guard: *guard, phantom: PhantomType::new() })
374 }
375
376 pub fn get_value(&self, index: usize) -> Option<&C> {
382 self.vec[index].as_ref().right().map(|(_, item)| item)
383 }
384
385 pub fn get_value_mut(&mut self, index: usize) -> Option<&mut C> {
391 self.vec[index].as_mut().right().map(|(_, item)| item)
392 }
393
394 pub fn ids(&self) -> ArenaItemsIds<'_, C> {
396 ArenaItemsIds(self.vec.iter().enumerate())
397 }
398
399 pub fn values(&self) -> ArenaItemsValues<'_, C> {
401 ArenaItemsValues(self.vec.iter())
402 }
403
404 pub fn values_mut(&mut self) -> ArenaItemsValuesMut<'_, C> {
406 ArenaItemsValuesMut(self.vec.iter_mut())
407 }
408
409 pub fn iter(&self) -> ArenaItemsIter<'_, C> {
411 ArenaItemsIter(self.vec.iter().enumerate())
412 }
413
414 pub fn iter_mut(&mut self) -> ArenaItemsIterMut<'_, C> {
416 ArenaItemsIterMut(self.vec.iter_mut().enumerate())
417 }
418
419 pub fn into_ids(self) -> ArenaItemsIntoIds<C> {
421 ArenaItemsIntoIds(self.vec.into_iter().enumerate())
422 }
423
424 pub fn into_values(self) -> ArenaItemsIntoValues<C> {
426 ArenaItemsIntoValues(self.vec.into_iter())
427 }
428}
429
430#[derive(Debug, Clone)]
434pub struct ArenaItemsIter<'a, C: Component>(
435 iter::Enumerate<slice::Iter<'a, Either<Option<usize>, (NonZeroUsize, C)>>>
436);
437
438impl<'a, C: Component> Iterator for ArenaItemsIter<'a, C> {
439 type Item = (Id<C>, &'a C);
440
441 fn next(&mut self) -> Option<Self::Item> {
442 loop {
443 match self.0.next() {
444 None => return None,
445 Some((_, Left(_))) => { },
446 Some((index, Right((guard, item)))) =>
447 return Some((Id { index, guard: *guard, phantom: PhantomType::new() }, item)),
448 }
449 }
450 }
451
452 fn size_hint(&self) -> (usize, Option<usize>) {
453 (0, self.0.size_hint().1)
454 }
455}
456
457impl<'a, C: Component> DoubleEndedIterator for ArenaItemsIter<'a, C> {
458 fn next_back(&mut self) -> Option<Self::Item> {
459 loop {
460 match self.0.next_back() {
461 None => return None,
462 Some((_, Left(_))) => { },
463 Some((index, Right((guard, item)))) =>
464 return Some((Id { index, guard: *guard, phantom: PhantomType::new() }, item)),
465 }
466 }
467 }
468}
469
470impl<'a, C: Component> FusedIterator for ArenaItemsIter<'a, C> { }
471
472#[derive(Debug)]
476pub struct ArenaItemsIterMut<'a, C: Component>(
477 iter::Enumerate<slice::IterMut<'a, Either<Option<usize>, (NonZeroUsize, C)>>>
478);
479
480impl<'a, C: Component> Iterator for ArenaItemsIterMut<'a, C> {
481 type Item = (Id<C>, &'a mut C);
482
483 fn next(&mut self) -> Option<Self::Item> {
484 loop {
485 match self.0.next() {
486 None => return None,
487 Some((_, Left(_))) => { },
488 Some((index, Right((guard, item)))) =>
489 return Some((Id { index, guard: *guard, phantom: PhantomType::new() }, item)),
490 }
491 }
492 }
493
494 fn size_hint(&self) -> (usize, Option<usize>) {
495 (0, self.0.size_hint().1)
496 }
497}
498
499impl<'a, C: Component> DoubleEndedIterator for ArenaItemsIterMut<'a, C> {
500 fn next_back(&mut self) -> Option<Self::Item> {
501 loop {
502 match self.0.next_back() {
503 None => return None,
504 Some((_, Left(_))) => { },
505 Some((index, Right((guard, item)))) =>
506 return Some((Id { index, guard: *guard, phantom: PhantomType::new() }, item)),
507 }
508 }
509 }
510}
511
512impl<'a, C: Component> FusedIterator for ArenaItemsIterMut<'a, C> { }
513
514#[derive(Debug, Clone)]
518pub struct ArenaItemsIds<'a, C: Component>(
519 iter::Enumerate<slice::Iter<'a, Either<Option<usize>, (NonZeroUsize, C)>>>
520);
521
522impl<'a, C: Component> Iterator for ArenaItemsIds<'a, C> {
523 type Item = Id<C>;
524
525 fn next(&mut self) -> Option<Self::Item> {
526 loop {
527 match self.0.next() {
528 None => return None,
529 Some((_, Left(_))) => { },
530 Some((index, Right((guard, _)))) => return Some(Id { index, guard: *guard, phantom: PhantomType::new() }),
531 }
532 }
533 }
534
535 fn size_hint(&self) -> (usize, Option<usize>) {
536 (0, self.0.size_hint().1)
537 }
538}
539
540impl<'a, C: Component> DoubleEndedIterator for ArenaItemsIds<'a, C> {
541 fn next_back(&mut self) -> Option<Self::Item> {
542 loop {
543 match self.0.next_back() {
544 None => return None,
545 Some((_, Left(_))) => { },
546 Some((index, Right((guard, _)))) => return Some(Id { index, guard: *guard, phantom: PhantomType::new() }),
547 }
548 }
549 }
550}
551
552impl<'a, C: Component> FusedIterator for ArenaItemsIds<'a, C> { }
553
554#[derive(Debug, Clone)]
558pub struct ArenaItemsValues<'a, C: Component>(
559 slice::Iter<'a, Either<Option<usize>, (NonZeroUsize, C)>>
560);
561
562impl<'a, C: Component> Iterator for ArenaItemsValues<'a, C> {
563 type Item = &'a C;
564
565 fn next(&mut self) -> Option<Self::Item> {
566 loop {
567 match self.0.next() {
568 None => return None,
569 Some(Left(_)) => { },
570 Some(Right((_, item))) => return Some(item),
571 }
572 }
573 }
574
575 fn size_hint(&self) -> (usize, Option<usize>) {
576 (0, self.0.size_hint().1)
577 }
578}
579
580impl<'a, C: Component> DoubleEndedIterator for ArenaItemsValues<'a, C> {
581 fn next_back(&mut self) -> Option<Self::Item> {
582 loop {
583 match self.0.next_back() {
584 None => return None,
585 Some(Left(_)) => { },
586 Some(Right((_, item))) => return Some(item),
587 }
588 }
589 }
590}
591
592impl<'a, C: Component> FusedIterator for ArenaItemsValues<'a, C> { }
593
594#[derive(Debug)]
598pub struct ArenaItemsValuesMut<'a, C: Component>(
599 slice::IterMut<'a, Either<Option<usize>, (NonZeroUsize, C)>>
600);
601
602impl<'a, C: Component> Iterator for ArenaItemsValuesMut<'a, C> {
603 type Item = &'a mut C;
604
605 fn next(&mut self) -> Option<Self::Item> {
606 loop {
607 match self.0.next() {
608 None => return None,
609 Some(Left(_)) => { },
610 Some(Right((_, item))) => return Some(item),
611 }
612 }
613 }
614
615 fn size_hint(&self) -> (usize, Option<usize>) {
616 (0, self.0.size_hint().1)
617 }
618}
619
620impl<'a, C: Component> DoubleEndedIterator for ArenaItemsValuesMut<'a, C> {
621 fn next_back(&mut self) -> Option<Self::Item> {
622 loop {
623 match self.0.next_back() {
624 None => return None,
625 Some(Left(_)) => { },
626 Some(Right((_, item))) => return Some(item),
627 }
628 }
629 }
630}
631
632impl<'a, C: Component> FusedIterator for ArenaItemsValuesMut<'a, C> { }
633
634#[derive(Debug)]
638pub struct ArenaItemsIntoIds<C: Component>(
639 #[cfg(feature="nightly")]
640 iter::Enumerate<vec::IntoIter<Either<Option<usize>, (NonZeroUsize, C)>, C::Alloc>>,
641
642 #[cfg(not(feature="nightly"))]
643 iter::Enumerate<vec::IntoIter<Either<Option<usize>, (NonZeroUsize, C)>>>,
644);
645
646impl<C: Component> Iterator for ArenaItemsIntoIds<C> {
647 type Item = Id<C>;
648
649 fn next(&mut self) -> Option<Self::Item> {
650 loop {
651 match self.0.next() {
652 None => return None,
653 Some((_, Left(_))) => { },
654 Some((index, Right((guard, _)))) => return Some(Id { index, guard, phantom: PhantomType::new() }),
655 }
656 }
657 }
658
659 fn size_hint(&self) -> (usize, Option<usize>) {
660 (0, self.0.size_hint().1)
661 }
662}
663
664impl<C: Component> DoubleEndedIterator for ArenaItemsIntoIds<C> {
665 fn next_back(&mut self) -> Option<Self::Item> {
666 loop {
667 match self.0.next_back() {
668 None => return None,
669 Some((_, Left(_))) => { },
670 Some((index, Right((guard, _)))) => return Some(Id { index, guard, phantom: PhantomType::new() }),
671 }
672 }
673 }
674}
675
676impl<C: Component> FusedIterator for ArenaItemsIntoIds<C> { }
677
678#[derive(Debug)]
682pub struct ArenaItemsIntoValues<C: Component>(
683 #[cfg(feature="nightly")]
684 vec::IntoIter<Either<Option<usize>, (NonZeroUsize, C)>, C::Alloc>,
685
686 #[cfg(not(feature="nightly"))]
687 vec::IntoIter<Either<Option<usize>, (NonZeroUsize, C)>>,
688);
689
690impl<C: Component> Iterator for ArenaItemsIntoValues<C> {
691 type Item = C;
692
693 fn next(&mut self) -> Option<Self::Item> {
694 loop {
695 match self.0.next() {
696 None => return None,
697 Some(Left(_)) => { },
698 Some(Right((_, item))) => return Some(item),
699 }
700 }
701 }
702
703 fn size_hint(&self) -> (usize, Option<usize>) {
704 (0, self.0.size_hint().1)
705 }
706}
707
708impl<C: Component> DoubleEndedIterator for ArenaItemsIntoValues<C> {
709 fn next_back(&mut self) -> Option<Self::Item> {
710 loop {
711 match self.0.next_back() {
712 None => return None,
713 Some(Left(_)) => { },
714 Some(Right((_, item))) => return Some(item),
715 }
716 }
717 }
718}
719
720impl<C: Component> FusedIterator for ArenaItemsIntoValues<C> { }
721
722#[derive(Debug, Clone)]
726pub struct ArenaItemsIntoIter<C: Component>(
727 #[cfg(feature="nightly")]
728 iter::Enumerate<vec::IntoIter<Either<Option<usize>, (NonZeroUsize, C)>, C::Alloc>>,
729
730 #[cfg(not(feature="nightly"))]
731 iter::Enumerate<vec::IntoIter<Either<Option<usize>, (NonZeroUsize, C)>>>,
732);
733
734impl<C: Component> Iterator for ArenaItemsIntoIter<C> {
735 type Item = (Id<C>, C);
736
737 fn next(&mut self) -> Option<Self::Item> {
738 loop {
739 match self.0.next() {
740 None => return None,
741 Some((_, Left(_))) => { },
742 Some((index, Right((guard, item)))) =>
743 return Some((Id { index, guard, phantom: PhantomType::new() }, item)),
744 }
745 }
746 }
747
748 fn size_hint(&self) -> (usize, Option<usize>) {
749 (0, self.0.size_hint().1)
750 }
751}
752
753impl<C: Component> DoubleEndedIterator for ArenaItemsIntoIter<C> {
754 fn next_back(&mut self) -> Option<Self::Item> {
755 loop {
756 match self.0.next_back() {
757 None => return None,
758 Some((_, Left(_))) => { },
759 Some((index, Right((guard, item)))) =>
760 return Some((Id { index, guard, phantom: PhantomType::new() }, item)),
761 }
762 }
763 }
764}
765
766impl<C: Component> FusedIterator for ArenaItemsIntoIter<C> { }
767
768impl<C: Component> IntoIterator for ArenaItems<C> {
769 type Item = (Id<C>, C);
770 type IntoIter = ArenaItemsIntoIter<C>;
771
772 fn into_iter(self) -> Self::IntoIter {
773 ArenaItemsIntoIter(self.vec.into_iter().enumerate())
774 }
775}
776
777impl<'a, C: Component> IntoIterator for &'a ArenaItems<C> {
778 type Item = (Id<C>, &'a C);
779 type IntoIter = ArenaItemsIter<'a, C>;
780
781 fn into_iter(self) -> Self::IntoIter { self.iter() }
782}
783
784mod forgettable_field {
785 use core::fmt::{self, Debug, Formatter};
786 use core::mem::{MaybeUninit, forget, replace};
787 use core::ops::{Deref, DerefMut};
788
789 pub struct ForgettableField<T>(MaybeUninit<T>);
790
791 impl<T> ForgettableField<T> {
792 pub const fn new(value: T) -> Self { ForgettableField(MaybeUninit::new(value)) }
793
794 pub fn into_inner(mut this: Self) -> T {
795 let inner = replace(&mut this.0, MaybeUninit::uninit());
796 forget(this);
797 unsafe { inner.assume_init() }
798 }
799
800 pub fn take_and_forget<Owner>(mut owner: Owner, f: impl FnOnce(&mut Owner) -> &mut Self) -> T {
801 let this = replace(f(&mut owner), ForgettableField(MaybeUninit::uninit()));
802 forget(owner);
803 Self::into_inner(this)
804 }
805 }
806
807 impl<T> Drop for ForgettableField<T> {
808 fn drop(&mut self) {
809 unsafe { self.0.assume_init_drop() }
810 }
811 }
812
813 impl<T> Deref for ForgettableField<T> {
814 type Target = T;
815
816 fn deref(&self) -> &T { unsafe { self.0.assume_init_ref() } }
817 }
818
819 impl<T> DerefMut for ForgettableField<T> {
820 fn deref_mut(&mut self) -> &mut T { unsafe { self.0.assume_init_mut() } }
821 }
822
823 impl<T: Default> Default for ForgettableField<T> {
824 fn default() -> Self { ForgettableField::new(T::default()) }
825 }
826
827 impl<T: Debug> Debug for ForgettableField<T> {
828 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
829 self.deref().fmt(f)
830 }
831 }
832}
833
834use forgettable_field::*;
835
836#[cfg(feature="nightly")]
838#[derive(Educe)]
839#[educe(Debug(bound = "C: Debug, C::Alloc: Debug"))]
840pub struct Arena<C: Component + 'static> {
841 guard_rng: Option<SmallRng>,
842 items: ForgettableField<ArenaItems<C>>,
843}
844
845#[cfg(not(feature="nightly"))]
847#[derive(Debug)]
848pub struct Arena<C: Component + 'static> {
849 guard_rng: Option<SmallRng>,
850 items: ForgettableField<ArenaItems<C>>,
851}
852
853#[cfg(feature="nightly")]
854include!("arena_nightly.rs");
855
856impl<C: Component> Arena<C> {
857 #[cfg(not(feature="nightly"))]
859 pub const fn new() -> Self {
860 Arena {
861 guard_rng: None,
862 items: ForgettableField::new(ArenaItems::new())
863 }
864 }
865
866 #[cfg(not(feature="nightly"))]
868 pub fn with_capacity(capacity: usize) -> Self {
869 Arena {
870 guard_rng: None,
871 items: ForgettableField::new(ArenaItems::with_capacity(capacity))
872 }
873 }
874
875 #[cfg(feature="nightly")]
877 pub const fn new_in(alloc: C::Alloc) -> Self {
878 Arena {
879 guard_rng: None,
880 items: ForgettableField::new(ArenaItems::new_in(alloc))
881 }
882 }
883
884 #[cfg(feature="nightly")]
886 pub fn with_capacity_in(capacity: usize, alloc: C::Alloc) -> Self {
887 Arena {
888 guard_rng: None,
889 items: ForgettableField::new(ArenaItems::with_capacity_in(capacity, alloc))
890 }
891 }
892
893 fn guard_rng(&mut self) -> &mut SmallRng {
894 if self.guard_rng.is_none() {
895 let seed = C::Class::token().0.fetch_add(1, Ordering::Relaxed);
896 self.guard_rng = Some(SmallRng::seed_from_u64(seed as u64));
897 }
898 unsafe { self.guard_rng.as_mut().unwrap_or_else(|| unreachable_unchecked()) }
899 }
900
901 pub fn into_items(#[allow(unused_mut)] mut self) -> ArenaItems<C> {
905 ForgettableField::take_and_forget(self, |x| &mut x.items)
906 }
907
908 pub fn items(&self) -> &ArenaItems<C> { &self.items }
912
913 pub fn items_mut(&mut self) -> &mut ArenaItems<C> { &mut self.items }
918
919 pub fn reserve(&mut self) {
928 if self.items().len_equals_to_min_capacity() {
929 self.items_mut().reserve(1);
930 }
931 }
932
933 pub fn reserve_exact(&mut self) {
945 if self.items().len_equals_to_min_capacity() {
946 self.items_mut().reserve_exact(1);
947 }
948 }
949
950 pub fn try_reserve(&mut self) -> Result<(), TryReserveError> {
959 if self.items().len_equals_to_min_capacity() {
960 self.items_mut().try_reserve(1)
961 } else {
962 Ok(())
963 }
964 }
965
966 pub fn try_reserve_exact(&mut self) -> Result<(), TryReserveError> {
979 if self.items().len_equals_to_min_capacity() {
980 self.items_mut().try_reserve_exact(1)
981 } else {
982 Ok(())
983 }
984 }
985
986 pub fn insert<T>(&mut self, component: impl FnOnce(Id<C>) -> (C, T)) -> T {
1005 let mut guard = 0usize.to_le_bytes();
1006 self.guard_rng().fill_bytes(&mut guard[..]);
1007 let guard = NonZeroUsize::new(usize::from_le_bytes(guard)).unwrap_or(unsafe { NonZeroUsize::new_unchecked(42) });
1008 if let Some(index) = self.items.vacancy {
1009 let id = Id { index, guard, phantom: PhantomType::new() };
1010 let (component, result) = component(id);
1011 let item = (guard, component);
1012 self.items.vacancy = replace(&mut self.items.vec[index], Right(item)).left()
1013 .unwrap_or_else(|| unsafe { unreachable_unchecked() });
1014 result
1015 } else {
1016 let index = self.items.len();
1017 let id = Id { index, guard, phantom: PhantomType::new() };
1018 let (component, result) = component(id);
1019 let item = (guard, component);
1020 self.items.vec.push(Right(item));
1021 result
1022 }
1023 }
1024
1025 pub fn remove(&mut self, id: Id<C>) -> C {
1031 let vacancy = self.items.vacancy;
1032 match replace(&mut self.items.vec[id.index], Left(vacancy)) {
1033 Left(vacancy) => {
1034 self.items.vec[id.index] = Left(vacancy);
1035 panic!("invalid id");
1036 },
1037 Right((guard, component)) => {
1038 if guard == id.guard {
1039 self.items.vacancy = Some(id.index);
1040 component
1041 } else {
1042 self.items.vec[id.index] = Right((guard, component));
1043 panic!("invalid id");
1044 }
1045 }
1046 }
1047 }
1048}
1049
1050#[cfg(feature="nightly")]
1051impl<C: Component> Default for Arena<C> where C::Alloc: ConstDefault {
1052 fn default() -> Self { Arena::new() }
1053}
1054
1055#[cfg(not(feature="nightly"))]
1056impl<C: Component> Default for Arena<C> {
1057 fn default() -> Self { Arena::new() }
1058}
1059
1060impl<C: Component> Index<Id<C>> for Arena<C> {
1061 type Output = C;
1062
1063 fn index(&self, id: Id<C>) -> &C {
1064 let &(guard, ref component) = self.items.vec[id.index].as_ref().right().expect("invalid id");
1065 if guard != id.guard { panic!("invalid id"); }
1066 component
1067 }
1068}
1069
1070impl<C: Component> IndexMut<Id<C>> for Arena<C> {
1071 fn index_mut(&mut self, id: Id<C>) -> &mut C {
1072 let &mut (guard, ref mut component) = self.items.vec[id.index].as_mut().right().expect("invalid id");
1073 if guard != id.guard { panic!("invalid id"); }
1074 component
1075 }
1076}
1077
1078#[doc(hidden)]
1079#[macro_export]
1080macro_rules! unexpected_token {
1081 () => { };
1082}
1083
1084#[macro_export]
1156macro_rules! Component {
1157 (
1158 ($($arg:tt)*)
1159 $vis:vis enum $name:ident
1160 $($token:tt)+
1161 ) => {
1162 $crate::generics_parse! {
1163 $crate::Component_impl {
1164 @args
1165 [, $($arg)*]
1166 [] []
1167 [$vis] [$name]
1168 }
1169 $($token)+
1170 }
1171 };
1172 (
1173 ($($arg:tt)*)
1174 $vis:vis struct $name:ident
1175 $($token:tt)+
1176 ) => {
1177 $crate::generics_parse! {
1178 $crate::Component_impl {
1179 @args
1180 [, $($arg)*]
1181 [] []
1182 [$vis] [$name]
1183 }
1184 $($token)+
1185 }
1186 };
1187}
1188
1189#[doc(hidden)]
1190#[macro_export]
1191macro_rules! Component_impl {
1192 (
1193 @args
1194 [$(,)?]
1195 [$($class:ident)?] [$($alloc:ty)?]
1196 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1197 ) => {
1198 $crate::Component_impl! {
1199 @impl [$vis] [$name] [$($class)?] [$($alloc)?]
1200 [$($g)*] [$($r)*] [$($w)*]
1201 }
1202 };
1203 (
1204 @args
1205 [, alloc = $alloc:ty $(, $($token:tt)*)?]
1206 [$($class:ident)?] []
1207 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1208 ) => {
1209 $crate::Component_impl! {
1210 @args
1211 [$(, $($token)*)?]
1212 [$($class)?] [$alloc]
1213 [$vis] [$name] [$($g)*] [$($r)*] [$($w)*]
1214 }
1215 };
1216 (
1217 @args
1218 [, alloc = $alloc:ty $(, $($token:tt)*)?]
1219 [$($class:ident)?] [$alloc_:ty]
1220 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1221 ) => {
1222 $crate::std_compile_error!("duplicated 'alloc' parameter");
1223 };
1224 (
1225 @args
1226 [, alloc = $($token:tt)*]
1227 [$($class:ident)?] [$($alloc:ty)?]
1228 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1229 ) => {
1230 $crate::std_compile_error!("invalid 'alloc' parameter");
1231 };
1232 (
1233 @args
1234 [, class = $class:ident $($token:tt)*]
1235 [] [$($alloc:ty)?]
1236 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1237 ) => {
1238 $crate::Component_impl! {
1239 @args
1240 [$($token)*]
1241 [$class] [$($alloc)?]
1242 [$vis] [$name] [$($g)*] [$($r)*] [$($w)*]
1243 }
1244 };
1245 (
1246 @args
1247 [, class = $class:ident $($token:tt)*]
1248 [$class_:ident] [$($alloc:ty)?]
1249 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1250 ) => {
1251 $crate::std_compile_error!("duplicated 'class' parameter");
1252 };
1253 (
1254 @args
1255 [, class = $token:tt $($tail:tt)*]
1256 [$($class:ident)?] [$($alloc:ty)?]
1257 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1258 ) => {
1259 $crate::unexpected_token!($token);
1260 $crate::std_compile_error!("invalid 'class' parameter");
1261 };
1262 (
1263 @args
1264 [, class = ]
1265 [$($class:ident)?] [$($alloc:ty)?]
1266 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1267 ) => {
1268 $crate::std_compile_error!("invalid 'class' parameter");
1269 };
1270 (
1271 @args
1272 [, $param:ident = $($token:tt)*]
1273 [$($class:ident)?] [$($alloc:ty)?]
1274 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1275 ) => {
1276 $crate::unexpected_token!($param);
1277 $crate::std_compile_error!($crate::std_concat!("unknown '", $crate::std_stringify!($param), "' parameter"));
1278 };
1279 (
1280 @args
1281 [, $token:tt $($tail:tt)*]
1282 [$($class:ident)?] [$($alloc:ty)?]
1283 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1284 ) => {
1285 $crate::unexpected_token!($token);
1286 $crate::std_compile_error!("invalid parameter");
1287 };
1288 (
1289 @args
1290 [$token:tt $($tail:tt)*]
1291 [$($class:ident)?] [$($alloc:ty)?]
1292 [$vis:vis] [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] $($body:tt)*
1293 ) => {
1294 $crate::unexpected_token!($token);
1295 $crate::std_compile_error!("comma expected");
1296 };
1297 (
1298 @impl [$vis:vis] [$name:ident] [] [$($alloc:ty)?] [] [] []
1299 ) => {
1300 $crate::Component_impl! { @self [$name] [$($alloc)?] }
1301 };
1302 (
1303 @impl [$vis:vis] [$name:ident] [$class:ident] [$($alloc:ty)?] [] [] []
1304 ) => {
1305 $crate::Component_impl! { @class [$vis] [$name] [$class] [$($alloc)?] [] [] [] }
1306 };
1307 (
1308 @impl [$vis:vis] [$name:ident] [] [$($alloc:ty)?] [$($g:tt)+] [$($r:tt)+] [$($w:tt)*]
1309 ) => {
1310 $crate::std_compile_error!($crate::std_concat!(
1311 "\
1312 generic component requires separate non-generic component class; \
1313 consider adding 'class' parameter: '#[derive(Component!(class=\
1314 ",
1315 $crate::std_stringify!($name),
1316 "Class)]'"
1317 ));
1318 };
1319 (
1320 @impl
1321 [$vis:vis] [$name:ident] [$class:ident]
1322 [$($alloc:ty)?] $g:tt $r:tt $w:tt
1323 ) => {
1324 $crate::Component_impl! { @class [$vis] [$name] [$class] [$($alloc)?] $g $r $w }
1325 };
1326 (
1327 @self [$name:ident] [$($alloc:ty)?]
1328 ) => {
1329 impl $crate::ComponentClass for $name {
1330 fn token() -> &'static $crate::ComponentClassToken {
1331 static TOKEN: $crate::ComponentClassToken = $crate::ComponentClassToken::new();
1332 &TOKEN
1333 }
1334 }
1335
1336 impl $crate::Component for $name {
1337 type Class = Self;
1338
1339 $(
1340 type Alloc = $alloc;
1341 )?
1342 }
1343 };
1344 (
1345 @class
1346 [$vis:vis] [$name:ident] [$class:ident]
1347 [$($alloc:ty)?] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
1348 ) => {
1349 #[allow(dead_code)]
1350 $vis enum $class { }
1351
1352 impl $crate::ComponentClass for $class {
1353 fn token() -> &'static $crate::ComponentClassToken {
1354 static TOKEN: $crate::ComponentClassToken = $crate::ComponentClassToken::new();
1355 &TOKEN
1356 }
1357 }
1358
1359 impl $($g)* $crate::Component for $name $($r)* $($w)* {
1360 type Class = $class;
1361
1362 $(
1363 type Alloc = $alloc;
1364 )?
1365 }
1366 };
1367}
1368
1369#[macro_export]
1413macro_rules! NewtypeComponentId {
1414 (
1415 ()
1416 $vis:vis struct $name:ident $($token:tt)*
1417 ) => {
1418 $crate::generics_parse! {
1419 $crate::NewtypeComponentId_impl {
1420 [$name]
1421 }
1422 $($token)*
1423 }
1424 };
1425}
1426
1427#[doc(hidden)]
1428#[macro_export]
1429macro_rules! NewtypeComponentId_impl {
1430 (
1431 [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*] (
1432 $(#[$id_attr:meta])* $(pub)? $id:ty
1433 $(, $(#[$phantom_attr:meta])* $(pub)? $phantom:ty)* $(,)?
1434 );
1435 ) => {
1436 impl $($g)* $crate::ComponentId for $name $($r)* $($w)* {
1437 fn from_raw(raw: $crate::RawId) -> Self {
1438 $name(
1439 <$id as $crate::ComponentId>::from_raw(raw)
1440 $(, <$phantom as $crate::std_default_Default>::default())*
1441 )
1442 }
1443
1444 fn into_raw(self) -> $crate::RawId {
1445 <$id as $crate::ComponentId>::into_raw(self.0)
1446 }
1447 }
1448 };
1449 (
1450 [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
1451 $token:tt $($tail:tt)*
1452 ) => {
1453 $crate::unexpected_token!($token);
1454 $crate::std_compile_error!("'NewtypeComponentId' supports deriving for non-empty tuple structs only");
1455 };
1456 (
1457 [$name:ident] [$($g:tt)*] [$($r:tt)*] [$($w:tt)*]
1458 ) => {
1459 $crate::std_compile_error!("'NewtypeComponentId' supports deriving for non-empty tuple structs only");
1460 };
1461}
1462
1463#[cfg(test)]
1464mod test {
1465 use macro_attr_2018::macro_attr;
1466 use quickcheck_macros::quickcheck;
1467
1468 use core::sync::atomic::{AtomicI8};
1469 use crate::*;
1470
1471 macro_attr! {
1472 #[derive(Component!(class=GenericOneArgComponent))]
1473 struct GenericOneArg<T>(T);
1474 }
1475
1476 macro_attr! {
1477 #[derive(Component!(class=GenericTwoArgsComponent))]
1478 struct GenericTwoArgs<A, B>(A, B);
1479 }
1480
1481 macro_attr! {
1482 #[derive(Component!)]
1483 struct Test {
1484 this: Id<Test>,
1485 value: i8
1486 }
1487 }
1488
1489 const fn _new_test_arena() -> Arena<Test> {
1490 Arena::new()
1491 }
1492
1493 macro_attr! {
1494 #[derive(Component!)]
1495 struct TestWithDrop {
1496 value: i8
1497 }
1498 }
1499
1500 static TEST_DROP: AtomicI8 = AtomicI8::new(-1);
1501
1502 const fn _new_test_with_drop_arena() -> Arena<TestWithDrop> {
1503 Arena::new()
1504 }
1505
1506 impl Drop for TestWithDrop {
1507 fn drop(&mut self) {
1508 TEST_DROP.store(self.value, Ordering::SeqCst);
1509 }
1510 }
1511
1512 #[quickcheck]
1513 fn new_arena_min_capacity_is_zero(capacity: Option<u8>) -> bool {
1514 let capacity = capacity.map(|capacity| capacity as usize);
1515 capacity.map_or_else(
1516 || <Arena::<Test>>::new(),
1517 |capacity| <Arena::<Test>>::with_capacity(capacity)
1518 ).items().min_capacity() == 0
1519 }
1520
1521 #[quickcheck]
1522 fn arena_contains_inserted_item(capacity: Option<u8>, value: i8) -> bool {
1523 let capacity = capacity.map(|capacity| capacity as usize);
1524 let mut arena = capacity.map_or_else(
1525 || Arena::new(),
1526 |capacity| Arena::with_capacity(capacity)
1527 );
1528 let id = arena.insert(|this| (Test { this, value }, this));
1529 arena[id].this == id && arena[id].value == value
1530 }
1531
1532 #[should_panic]
1533 #[test]
1534 fn foreign_id_cause_panic() {
1535 let mut arena = Arena::new();
1536 let id = arena.insert(|this| (Test { this, value: 7 }, this)).into_raw();
1537 let id = Id::from_raw((id.0, unsafe { NonZeroUsize::new_unchecked(17) }));
1538 let _ = &arena[id];
1539 }
1540
1541 #[test]
1542 fn drop_components() {
1543 {
1544 let mut arena = Arena::new();
1545 arena.insert(|this| (TestWithDrop { value: 7 }, this)).into_raw();
1546 TEST_DROP.store(-1, Ordering::SeqCst);
1547 }
1548 assert_eq!(TEST_DROP.load(Ordering::SeqCst), 7);
1549 }
1550
1551 macro_attr! {
1552 #[derive(NewtypeComponentId!, Educe)]
1553 #[educe(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
1554 struct IdWrap1(#[allow(dead_code)] Id<Test>);
1555 }
1556
1557 macro_attr! {
1558 #[derive(NewtypeComponentId!, Educe)]
1559 #[educe(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
1560 struct IdWrap2<X>(Id<Test>, PhantomType<X>);
1561 }
1562
1563 macro_attr! {
1564 #[derive(NewtypeComponentId!, Educe)]
1565 #[educe(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
1566 struct IdWrap3<X, Y: Copy>(Id<Test>, PhantomType<X>, PhantomType<Y>);
1567 }
1568
1569 macro_attr! {
1570 #[derive(NewtypeComponentId!, Educe)]
1571 #[educe(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
1572 struct IdWrap4<X, Y: Copy>((), PhantomType<X>, PhantomType<Y>);
1573 }
1574}
1575
1576#[cfg(all(test, feature="nightly"))]
1577mod test_nightly {
1578 use macro_attr_2018::macro_attr;
1579 use crate::*;
1580
1581 macro_attr! {
1582 #[derive(Component!(alloc=&'static dyn Allocator))]
1583 struct TestComponent {
1584 }
1585 }
1586}