components_arena/
lib.rs

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//! ## Feature flags
15#![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
61/// [Component class](ComponentClass) static shared data.
62/// The return type of the [`ComponentClass::token`] function.
63///
64/// The [`ComponentClass::token`] function
65/// is essential for components arena internal mechanic.
66pub struct ComponentClassToken(AtomicUsize);
67
68impl ComponentClassToken {
69    /// Creates new `ComponentClassLock` instance.
70    ///
71    /// The function is `const`, and can be used for static initialization.
72    pub const fn new() -> Self { ComponentClassToken(AtomicUsize::new(0)) }
73}
74
75impl Default for ComponentClassToken {
76    fn default() -> Self { ComponentClassToken::new() }
77}
78
79/// An utility trait describing a specific component type.
80///
81/// Normally for a non-generic component type
82/// the component type itself implements `ComponentClass`.
83///
84/// For generic components it would be difficult to have
85/// an own [`ComponentClassToken`] instance for every specialization because Rust
86/// does not have "generic statics" feature.
87///
88/// So, if some component type `X` is generic, normally you should introduce
89/// common non-generic uninhabited type `XComponent` and implement
90/// `ComponentClass` for this synthetic type.
91///
92/// Correct implementation should return reference to the one and same
93/// `ComponentClassToken` instance from the [`token`](ComponentClass::token) function.
94/// Also it should be guaranteed that no other `ComponentClass` implementation
95/// returns same `ComponentClassLock` instance.
96/// This requirements can be easily satisfied with private static:
97///
98/// ```rust
99/// # use components_arena::{ComponentClass, ComponentClassToken};
100/// #
101/// struct MyComponent { /* ... */ }
102///
103/// impl ComponentClass for MyComponent {
104///     fn token() -> &'static ComponentClassToken {
105///         static TOKEN: ComponentClassToken = ComponentClassToken::new();
106///         &TOKEN
107///     }
108/// }
109/// ```
110pub trait ComponentClass {
111    /// Essential for components arena internal mechanic.
112    fn token() -> &'static ComponentClassToken where Self: Sized;
113}
114
115/// An implementer of the `Component` trait is a type, whose values can be placed into
116/// [`Arena`] container.
117///
118/// Normally, the implementation of this trait is derived
119/// using the [`Component!`](Component!) macro.
120pub trait Component {
121    /// Component class.
122    ///
123    /// Normally it is `Self` for non-generic types, and
124    /// non-generic synthetic uninhabited type for generic ones.
125    type Class: ComponentClass;
126
127    /// Component allocator.
128    ///
129    /// [`Arena`]`<Self>` will use this allocator to allocate memory
130    /// for components array.
131    #[cfg(feature="nightly")]
132    type Alloc: Allocator = Global;
133}
134
135/// [`Arena`] item handle.
136#[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/// A (mostly read-only) inner container holding [`Arena`] items.
157/// While [`Arena`] itself is unique (i.e. non-clonable) object,
158/// arena ['items'](Arena::items) could be cloned.
159#[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    /// An amount of memory required to hold one component.
172    ///
173    /// This information can be useful for memory management fine-tuning.
174    pub const fn item_size() -> usize {
175        size_of::<ArenaItem<C>>()
176    }
177
178    /// An alignment of a cell, holding a component with all required metadata.
179    ///
180    /// This information can be useful for memory management fine-tuning.
181    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    /// Returns a reference to the underlying allocator.
218    #[cfg(feature="nightly")]
219    pub fn allocator(&self) -> &C::Alloc { self.vec.allocator() }
220
221    /// Returns the number of elements the arena can hold without reallocating.
222    pub fn capacity(&self) -> usize { self.vec.capacity() }
223
224    /// Returns the number of elements in the arena.
225    ///
226    /// This function has linear worst-case complexity.
227    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    /// Returns true iff the number of elements in the arena equals the maximum number of elements ever in the arena.
238    ///
239    /// Because the arena capacity cannot be less than `min_capacity`, the returned false means
240    /// there is space for at least one more item.
241    ///
242    /// The returned value equals to `self.len() == self.min_capacity()`, but unlike [`len`](ArenaItems::len)
243    /// this function has constant complexity.
244    pub fn len_equals_to_min_capacity(&self) -> bool {
245        self.vacancy.is_none()
246    }
247
248    /// Returns `true` if the arena contains no elements.
249    ///
250    /// This function has linear worst-case complexity.
251    pub fn is_empty(&self) -> bool { self.vec.iter().all(|x| x.is_left()) }
252
253    /// Returns the maximum number of elements ever in the arena.
254    /// The arena capacity cannot be less than `min_capacity`.
255    ///
256    /// Arena `min_capacity` never decreases.
257    ///
258    /// # Examples
259    ///
260    /// ```rust
261    /// # use macro_attr_2018::macro_attr;
262    /// # use components_arena::{Component, Arena};
263    /// #
264    /// # macro_attr! {
265    /// #     #[derive(Component!)]
266    /// #     struct MyComponent { /* ... */ }
267    /// # }
268    /// #
269    /// # fn main() {
270    /// let mut arena = Arena::new();
271    /// assert_eq!(arena.items().min_capacity(), 0);
272    /// let id_1 = arena.insert(|id| (MyComponent { /* ... */ }, id));
273    /// assert_eq!(arena.items().min_capacity(), 1);
274    /// let id_2 = arena.insert(|id| (MyComponent { /* ... */ }, id));
275    /// assert_eq!(arena.items().min_capacity(), 2);
276    /// arena.remove(id_1);
277    /// assert_eq!(arena.items().min_capacity(), 2);
278    /// let id_3 = arena.insert(|id| (MyComponent { /* ... */ }, id));
279    /// assert_eq!(arena.items().min_capacity(), 2);
280    /// let id_4 = arena.insert(|id| (MyComponent { /* ... */ }, id));
281    /// assert_eq!(arena.items().min_capacity(), 3);
282    /// # }
283    /// ```
284    pub fn min_capacity(&self) -> usize { self.vec.len() }
285
286    /// Reserves capacity for at least `additional` more elements.
287    /// The collection may reserve more space to avoid frequent reallocations.
288    /// After calling `reserve`, capacity will be greater than or equal to
289    /// `self.min_capacity() + additional`. Does nothing if capacity is already sufficient.
290    ///
291    /// # Panics
292    ///
293    /// Panics if the new capacity overflows usize.
294    pub fn reserve(&mut self, additional: usize) { self.vec.reserve(additional) }
295
296    /// Reserves the minimum capacity for exactly `additional` more elements.
297    /// After calling `reserve_exact`, capacity will be greater than or equal to
298    /// `self.min_capacity() + additional`. Does nothing if the capacity is already sufficient.
299    ///
300    /// Note that the allocator may give the collection more space than it requests.
301    /// Therefore, capacity can not be relied upon to be precisely minimal.
302    /// Prefer [`reserve`](ArenaItems::reserve) if future insertions are expected.
303    ///
304    /// # Panics
305    ///
306    /// Panics if the new capacity overflows usize.
307    pub fn reserve_exact(&mut self, additional: usize) { self.vec.reserve_exact(additional) }
308
309    /// Shrinks the capacity of the arena with a lower bound.
310    ///
311    /// The capacity will remain at least as large as both the [`min_capacity`](ArenaItems::min_capacity)
312    /// and the supplied value.
313    pub fn shrink_to(&mut self, min_capacity: usize) { self.vec.shrink_to(min_capacity) }
314
315    /// Shrinks the capacity of the vector as much as possible.
316    ///
317    /// It will drop down as close as possible to the [`min_capacity`](ArenaItems::min_capacity)
318    /// but the allocator may still inform the arena that there is space for a few more elements.
319    pub fn shrink_to_fit(&mut self) { self.vec.shrink_to_fit() }
320
321    /// Tries to reserve capacity for at least additional more elements.
322    /// The collection may reserve more space to avoid frequent reallocations.
323    /// After calling `try_reserve`, capacity will be greater than or equal
324    /// to `self.min_capacity() + additional`. Does nothing if capacity is already sufficient.
325    ///
326    /// # Errors
327    ///
328    /// If the capacity overflows, or the allocator reports a failure, then an error is returned.
329    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
330        self.vec.try_reserve(additional)
331    }
332
333    /// Tries to reserve capacity for exactly `additional` more elements.
334    /// The collection may reserve more space to avoid frequent reallocations.
335    /// After calling `try_reserve_exact`, capacity will be greater than or equal
336    /// to `self.min_capacity() + additional`. Does nothing if capacity is already sufficient.
337    ///
338    /// Note that the allocator may give the collection more space than it requests.
339    /// Therefore, capacity can not be relied upon to be precisely minimal.
340    /// Prefer [`try_reserve`](ArenaItems::try_reserve) if future insertions are expected.
341    ///
342    /// # Errors
343    ///
344    /// If the capacity overflows, or the allocator reports a failure, then an error is returned.
345    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
346        self.vec.try_reserve_exact(additional)
347    }
348
349    /// Returns reference to the item occupying `index` place with its [`Id`], or `None` if there is no such.
350    ///
351    /// # Panics
352    ///
353    /// Panics if `index` is greater than or equal to [`min_capacity()`](ArenaItems::min_capacity).
354    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    /// Returns mutable reference to the item occupying `index` place with its [`Id`], or `None` if there is no such.
359    ///
360    /// # Panics
361    ///
362    /// Panics if `index` is greater than or equal to [`min_capacity()`](ArenaItems::min_capacity).
363    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    /// Returns [`Id`] of item occupying `index` place, or `None` if there is no such.
368    ///
369    /// # Panics
370    ///
371    /// Panics if `index` is greater than or equal to [`min_capacity()`](ArenaItems::min_capacity).
372    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    /// Returns reference to the item occupying `index` place, or `None` if there is no such.
377    ///
378    /// # Panics
379    ///
380    /// Panics if `index` is greater than or equal to [`min_capacity()`](ArenaItems::min_capacity).
381    pub fn get_value(&self, index: usize) -> Option<&C> {
382        self.vec[index].as_ref().right().map(|(_, item)| item)
383    }
384
385    /// Returns mutable reference to the item occupying `index` place, or `None` if there is no such.
386    ///
387    /// # Panics
388    ///
389    /// Panics if `index` is greater than or equal to [`min_capacity()`](ArenaItems::min_capacity).
390    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    /// Returns an iterator over all item ids.
395    pub fn ids(&self) -> ArenaItemsIds<'_, C> {
396        ArenaItemsIds(self.vec.iter().enumerate())
397    }
398
399    /// Returns an iterator over all items.
400    pub fn values(&self) -> ArenaItemsValues<'_, C> {
401        ArenaItemsValues(self.vec.iter())
402    }
403
404    /// Returns a mutable iterator over all items.
405    pub fn values_mut(&mut self) -> ArenaItemsValuesMut<'_, C> {
406        ArenaItemsValuesMut(self.vec.iter_mut())
407    }
408
409    /// Returns an iterator over all items combined with their ids.
410    pub fn iter(&self) -> ArenaItemsIter<'_, C> {
411        ArenaItemsIter(self.vec.iter().enumerate())
412    }
413
414    /// Returns a mutable iterator over all items combined with their ids.
415    pub fn iter_mut(&mut self) -> ArenaItemsIterMut<'_, C> {
416        ArenaItemsIterMut(self.vec.iter_mut().enumerate())
417    }
418
419    /// Transforms the container into an iterator over all items ids.
420    pub fn into_ids(self) -> ArenaItemsIntoIds<C> {
421        ArenaItemsIntoIds(self.vec.into_iter().enumerate())
422    }
423
424    /// Transforms the container into an iterator over all items.
425    pub fn into_values(self) -> ArenaItemsIntoValues<C> {
426        ArenaItemsIntoValues(self.vec.into_iter())
427    }
428}
429
430/// An iterator over all items combined with their ids.
431///
432/// Usually created by the [`ArenaItems::iter`](ArenaItems::iter) method.
433#[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/// A mutable iterator over all items combined with their ids.
473///
474/// Usually created by the [`ArenaItems::iter_mut`](ArenaItems::iter_mut) method.
475#[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/// An iterator over all items ids.
515///
516/// Usually created by the [`ArenaItems::ids`](ArenaItems::ids) method.
517#[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/// An iterator over all items.
555///
556/// Usually created by the [`ArenaItems::values`](ArenaItems::values) method.
557#[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/// A mutable iterator over all items.
595///
596/// Usually created by the [`ArenaItems::values_mut`](ArenaItems::values_mut) method.
597#[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/// An iterator over all items ids.
635///
636/// Usually created by the [`ArenaItems::into_ids`](ArenaItems::into_ids) method.
637#[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/// An iterator over all items.
679///
680/// Usually created by the [`ArenaItems::into_values`](ArenaItems::into_values) method.
681#[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/// An iterator over all items combined with their ids.
723///
724/// Usually created by the [`ArenaItems::into_iter`](ArenaItems::into_iter) method.
725#[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/// Unordered container with random access.
837#[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/// Unordered container with random access.
846#[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    /// Creates an arena instance.
858    #[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    /// Creates an arena instance with the specified initial capacity.
867    #[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    /// Creates an arena instance.
876    #[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    /// Creates an arena instance with the specified initial capacity.
885    #[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    /// Returns contained items packed in a special container.
902    /// While arena itself is unique (i.e. non-clonable) object,
903    /// this special container could be cloned.
904    pub fn into_items(#[allow(unused_mut)] mut self) -> ArenaItems<C> {
905        ForgettableField::take_and_forget(self, |x| &mut x.items)
906    }
907
908    /// Returns reference to contained items packed in a special container.
909    /// While arena itself is unique (i.e. non-clonable) object,
910    /// this special container could be cloned.
911    pub fn items(&self) -> &ArenaItems<C> { &self.items }
912
913    /// Returns mutable reference to contained items packed in
914    /// a (mostly read-only) special container.
915    /// While arena itself is unique (i.e. non-clonable) object,
916    /// this special container could be cloned.
917    pub fn items_mut(&mut self) -> &mut ArenaItems<C> { &mut self.items }
918
919    /// Reserves capacity for at least one more element.
920    /// The collection may reserve more space to avoid frequent reallocations.
921    /// After calling `reserve`, capacity will be greater than or equal to
922    /// `self.items().len() + 1`. Does nothing if capacity is already sufficient.
923    ///
924    /// # Panics
925    ///
926    /// Panics if the new capacity overflows usize.
927    pub fn reserve(&mut self) {
928        if self.items().len_equals_to_min_capacity() {
929            self.items_mut().reserve(1);
930        }
931    }
932
933    /// Reserves the minimum capacity for exactly one more element.
934    /// After calling `reserve_exact`, capacity will be greater than or equal to
935    /// `self.items().len() + 1`. Does nothing if the capacity is already sufficient.
936    ///
937    /// Note that the allocator may give the collection more space than it requests.
938    /// Therefore, capacity can not be relied upon to be precisely minimal.
939    /// Prefer [`reserve`](Arena::reserve) if future insertions are expected.
940    ///
941    /// # Panics
942    ///
943    /// Panics if the new capacity overflows usize.
944    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    /// Tries to reserve capacity for at least one more element.
951    /// The collection may reserve more space to avoid frequent reallocations.
952    /// After calling `try_reserve`, capacity will be greater than or equal
953    /// to `self.items().len() + 1`. Does nothing if capacity is already sufficient.
954    ///
955    /// # Errors
956    ///
957    /// If the capacity overflows, or the allocator reports a failure, then an error is returned.
958    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    /// Tries to reserve capacity for exactly one more element.
967    /// The collection may reserve more space to avoid frequent reallocations.
968    /// After calling `try_reserve_exact`, capacity will be greater than or equal
969    /// to `self.items().len() + 1`. Does nothing if capacity is already sufficient.
970    ///
971    /// Note that the allocator may give the collection more space than it requests.
972    /// Therefore, capacity can not be relied upon to be precisely minimal.
973    /// Prefer [`try_reserve`](Arena::try_reserve) if future insertions are expected.
974    ///
975    /// # Errors
976    ///
977    /// If the capacity overflows, or the allocator reports a failure, then an error is returned.
978    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    /// Place new component into the arena.
987    ///
988    /// # Examples
989    ///
990    /// ```rust
991    /// # use macro_attr_2018::macro_attr;
992    /// # use components_arena::{Component, Arena};
993    /// #
994    /// # macro_attr! {
995    /// #     #[derive(Component!)]
996    /// #     struct MyComponent { /* ... */ }
997    /// # }
998    /// #
999    /// # fn main() {
1000    /// let mut arena = Arena::new();
1001    /// let new_component_id = arena.insert(|id| (MyComponent { /* ... */ }, id));
1002    /// # }
1003    /// ```
1004    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    /// Removes component with provided id.
1026    ///
1027    /// The arena tries to detect invalid provided id (i.e. foreign, or previously dropped),
1028    /// and panics if such detection hits. But it is important to pay respect to the fact
1029    /// there is small probability that invalid id will not be intercepted.
1030    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 attribute](https://crates.io/crates/macro-attr-2018) for deriving [`Component`](trait@Component) trait.
1085///
1086/// Accepts input in the following form:
1087///
1088/// ```ignore
1089/// ($($(
1090///     $param
1091/// ),+ $(,)?)?)
1092/// $vis:vis $(enum | struct) $name:ident
1093/// $(
1094///     <$generics>
1095///     $($tokens_between_generics_and_where_clause:tt)*
1096///     $(where $where_clause)?
1097/// )?
1098/// $( ; | { $($body:tt)* } )
1099/// ```
1100///
1101/// where $param may be in any of following forms:
1102///
1103/// ```ignore
1104/// class = $Class:ident
1105/// ```
1106///
1107/// ```ignore
1108/// alloc = $Allocator:ty
1109/// ```
1110///
1111/// # Examples
1112///
1113/// ## Non-generic component
1114///
1115/// ```rust
1116/// # use macro_attr_2018::macro_attr;
1117/// # use components_arena::{Component, Arena};
1118/// #
1119/// macro_attr! {
1120///     #[derive(Component!)]
1121///     struct Item { /* ... */ }
1122/// }
1123///
1124/// // ...
1125///
1126/// # fn main() {
1127/// let mut arena = Arena::new();
1128/// let id = arena.insert(|id| (Item { /* ... */ }, id));
1129/// # }
1130/// ```
1131///
1132/// ## Generic component
1133///
1134/// ```rust
1135/// # use macro_attr_2018::macro_attr;
1136/// # use components_arena::{Component, Arena};
1137/// #
1138/// macro_attr! {
1139///     #[derive(Component!(class=ItemComponent))]
1140///     struct Item<T> {
1141///         context: T
1142///     }
1143/// }
1144///
1145/// // ...
1146///
1147/// # fn main() {
1148/// let mut arena_u8 = Arena::new();
1149/// let _ = arena_u8.insert(|id| (Item { context: 7u8 }, id));
1150///
1151/// let mut arena_u32 = Arena::new();
1152/// let _ = arena_u32.insert(|id| (Item { context: 7u32 }, id));
1153/// # }
1154/// ```
1155#[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 attribute](https://crates.io/crates/macro-attr-2018)
1370/// for deriving [`ComponentId`](trait@ComponentId) trait.
1371///
1372/// Accepts input in any of following forms:
1373///
1374/// ```ignore
1375/// ()
1376/// $vis:vis struct $name:ident (
1377///     $(#[$id_attr:meta])* $(pub)? $id:ty
1378///     $(, $(#[$phantom_attr:meta])* $(pub)? $phantom:ty)* $(,)?
1379/// );
1380/// ```
1381///
1382/// ```ignore
1383/// ()
1384/// $vis:vis struct $name:ident <$generics> (
1385///     $(#[$id_attr:meta])* $(pub)? $id:ty
1386///     $(, $(#[$phantom_attr:meta])* $(pub)? $phantom:ty)* $(,)?
1387/// ) $(where $where_clause)?;
1388/// ```
1389///
1390/// # Examples
1391///
1392/// ```rust
1393/// # use educe::Educe;
1394/// # use macro_attr_2018::macro_attr;
1395/// use components_arena::{Component, Id, NewtypeComponentId};
1396/// use phantom_type::PhantomType;
1397///
1398/// # macro_attr! {
1399/// #    #[derive(Component!(class=ItemNodeComponent))]
1400/// #    struct ItemNode<Tag> {
1401/// #        /* ... */
1402/// #        tag: Tag
1403/// #    }
1404/// # }
1405/// #
1406/// macro_attr! {
1407///     #[derive(Educe, NewtypeComponentId!)]
1408///     #[educe(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
1409///     pub struct Item<Tag, X>(Id<ItemNode<Tag>>, PhantomType<X>);
1410/// }
1411/// ```
1412#[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}