1 //! [![](https://img.shields.io/crates/v/id-arena.svg)](https://crates.io/crates/id-arena)
2 //! [![](https://img.shields.io/crates/d/id-arena.svg)](https://crates.io/crates/id-arena)
3 //! [![Travis CI Build Status](https://travis-ci.org/fitzgen/id-arena.svg?branch=master)](https://travis-ci.org/fitzgen/id-arena)
5 //! A simple, id-based arena.
9 //! Allocate objects and get an identifier for that object back, *not* a
10 //! reference to the allocated object. Given an id, you can get a shared or
11 //! exclusive reference to the allocated object from the arena. This id-based
12 //! approach is useful for constructing mutable graph data structures.
14 //! If you want allocation to return a reference, consider [the `typed-arena`
15 //! crate](https://github.com/SimonSapin/rust-typed-arena/) instead.
19 //! This arena does not support deletion, which makes its implementation simple
20 //! and allocation fast. If you want deletion, you need a way to solve the ABA
21 //! problem. Consider using [the `generational-arena`
22 //! crate](https://github.com/fitzgen/generational-arena) instead.
26 //! This crate's arenas can only contain objects of a single type `T`. If you
27 //! need an arena of objects with heterogeneous types, consider another crate.
29 //! ## `#![no_std]` Support
31 //! Requires the `alloc` nightly feature. Disable the on-by-default `"std"` feature:
34 //! [dependencies.id-arena]
36 //! default-features = false
39 //! ## `rayon` Support
41 //! If the `rayon` feature of this crate is activated:
45 //! id-arena = { version = "2", features = ["rayon"] }
48 //! then you can use [`rayon`](https://crates.io/crates/rayon)'s support for
49 //! parallel iteration. The `Arena` type will have a `par_iter` family of
50 //! methods where appropriate.
55 //! use id_arena::{Arena, Id};
57 //! type AstNodeId = Id<AstNode>;
59 //! #[derive(Debug, Eq, PartialEq)]
60 //! pub enum AstNode {
81 //! let mut ast_nodes = Arena::<AstNode>::new();
83 //! // Create the AST for `a * (b + 3)`.
84 //! let three = ast_nodes.alloc(AstNode::Const(3));
85 //! let b = ast_nodes.alloc(AstNode::Var("b".into()));
86 //! let b_plus_three = ast_nodes.alloc(AstNode::Add {
90 //! let a = ast_nodes.alloc(AstNode::Var("a".into()));
91 //! let a_times_b_plus_three = ast_nodes.alloc(AstNode::Mul {
93 //! rhs: b_plus_three,
96 //! // Can use indexing to access allocated nodes.
97 //! assert_eq!(ast_nodes[three], AstNode::Const(3));
100 #![forbid(unsafe_code)]
101 #![deny(missing_debug_implementations)]
102 #![deny(missing_docs)]
103 // In no-std mode, use the alloc crate to get `Vec`.
105 #![cfg_attr(not(feature = "std"), feature(alloc))]
107 use core::cmp::Ordering;
109 use core::hash::{Hash, Hasher};
111 use core::marker::PhantomData;
114 use core::sync::atomic::{self, AtomicUsize, ATOMIC_USIZE_INIT};
116 #[cfg(not(feature = "std"))]
118 #[cfg(not(feature = "std"))]
119 use alloc::vec::{self, Vec};
121 #[cfg(feature = "std")]
123 #[cfg(feature = "std")]
124 use std::vec::{self, Vec};
126 #[cfg(feature = "rayon")]
128 #[cfg(feature = "rayon")]
131 /// A trait representing the implementation behavior of an arena and how
132 /// identifiers are represented.
134 /// ## When should I implement `ArenaBehavior` myself?
136 /// Usually, you should just use `DefaultArenaBehavior`, which is simple and
137 /// correct. However, there are some scenarios where you might want to implement
138 /// `ArenaBehavior` yourself:
140 /// * **Space optimizations:** The default identifier is two words in size,
141 /// which is larger than is usually necessary. For example, if you know that an
142 /// arena *cannot* contain more than 256 items, you could make your own
143 /// identifier type that stores the index as a `u8` and then you can save some
146 /// * **Trait Coherence:** If you need to implement an upstream crate's traits
147 /// for identifiers, then defining your own identifier type allows you to work
148 /// with trait coherence rules.
150 /// * **Share identifiers across arenas:** You can coordinate and share
151 /// identifiers across different arenas to enable a "struct of arrays" style
152 /// data representation.
153 pub trait ArenaBehavior {
154 /// The identifier type.
157 /// Construct a new object identifier from the given index and arena
162 /// Implementations are allowed to panic if the given index is larger than
163 /// the underlying storage (e.g. the implementation uses a `u8` for storing
164 /// indices and the given index value is larger than 255).
165 fn new_id(arena_id: u32, index: usize) -> Self::Id;
167 /// Get the given identifier's index.
168 fn index(Self::Id) -> usize;
170 /// Get the given identifier's arena id.
171 fn arena_id(Self::Id) -> u32;
173 /// Construct a new arena identifier.
175 /// This is used to disambiguate `Id`s across different arenas. To make
176 /// identifiers with the same index from different arenas compare false for
177 /// equality, return a unique `u32` on every invocation. This is the
178 /// default, provided implementation's behavior.
180 /// To make identifiers with the same index from different arenas compare
181 /// true for equality, return the same `u32` on every invocation.
182 fn new_arena_id() -> u32 {
183 static ARENA_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
184 ARENA_COUNTER.fetch_add(1, atomic::Ordering::SeqCst) as u32
188 /// An identifier for an object allocated within an arena.
192 _ty: PhantomData<fn() -> T>,
195 impl<T> fmt::Debug for Id<T> {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 f.debug_struct("Id").field("idx", &self.idx).finish()
201 impl<T> Copy for Id<T> {}
203 impl<T> Clone for Id<T> {
205 fn clone(&self) -> Id<T> {
210 impl<T> PartialEq for Id<T> {
212 fn eq(&self, rhs: &Self) -> bool {
213 self.arena_id == rhs.arena_id && self.idx == rhs.idx
217 impl<T> Eq for Id<T> {}
219 impl<T> Hash for Id<T> {
221 fn hash<H: Hasher>(&self, h: &mut H) {
222 self.arena_id.hash(h);
227 impl<T> PartialOrd for Id<T> {
228 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
233 impl<T> Ord for Id<T> {
234 fn cmp(&self, rhs: &Self) -> Ordering {
237 .then(self.idx.cmp(&rhs.idx))
242 /// Get the index within the arena that this id refers to.
244 pub fn index(&self) -> usize {
249 /// The default `ArenaBehavior` implementation.
250 #[derive(Clone, Debug, PartialEq, Eq)]
251 pub struct DefaultArenaBehavior<T> {
252 _phantom: PhantomData<fn() -> T>,
255 impl<T> ArenaBehavior for DefaultArenaBehavior<T> {
259 fn new_id(arena_id: u32, idx: usize) -> Self::Id {
268 fn index(id: Self::Id) -> usize {
273 fn arena_id(id: Self::Id) -> u32 {
278 /// An arena of objects of type `T`.
281 /// use id_arena::Arena;
283 /// let mut arena = Arena::<&str>::new();
285 /// let a = arena.alloc("Albert");
286 /// assert_eq!(arena[a], "Albert");
288 /// arena[a] = "Alice";
289 /// assert_eq!(arena[a], "Alice");
291 #[derive(Clone, Debug, PartialEq, Eq)]
292 pub struct Arena<T, A = DefaultArenaBehavior<T>> {
295 _phantom: PhantomData<fn() -> A>,
298 impl<T, A> Default for Arena<T, A>
303 fn default() -> Arena<T, A> {
305 arena_id: A::new_arena_id(),
307 _phantom: PhantomData,
312 impl<T, A> Arena<T, A>
316 /// Construct a new, empty `Arena`.
319 /// use id_arena::Arena;
321 /// let mut arena = Arena::<usize>::new();
325 pub fn new() -> Arena<T, A> {
329 /// Construct a new, empty `Arena` with capacity for the given number of
333 /// use id_arena::Arena;
335 /// let mut arena = Arena::<usize>::with_capacity(100);
336 /// for x in 0..100 {
337 /// arena.alloc(x * x);
341 pub fn with_capacity(capacity: usize) -> Arena<T, A> {
343 arena_id: A::new_arena_id(),
344 items: Vec::with_capacity(capacity),
345 _phantom: PhantomData,
349 /// Allocate `item` within this arena and return its id.
352 /// use id_arena::Arena;
354 /// let mut arena = Arena::<usize>::new();
355 /// let _id = arena.alloc(42);
360 /// Panics if the number of elements in the arena overflows a `usize` or
361 /// `Id`'s index storage representation.
363 pub fn alloc(&mut self, item: T) -> A::Id {
364 let id = self.next_id();
365 self.items.push(item);
369 /// Allocate an item with the id that it will be assigned.
371 /// This is useful for structures that want to store their id as their own
375 /// use id_arena::{Arena, Id};
381 /// let mut arena = Arena::<Cat>::new();
383 /// let kitty = arena.alloc_with_id(|id| Cat { id });
384 /// assert_eq!(arena[kitty].id, kitty);
387 pub fn alloc_with_id(&mut self, f: impl FnOnce(A::Id) -> T) -> A::Id {
388 let id = self.next_id();
393 /// Get the id that will be used for the next item allocated into this
396 /// If you are allocating a `struct` that wants to have its id as a member
397 /// of itself, prefer the less error-prone `Arena::alloc_with_id` method.
399 pub fn next_id(&self) -> A::Id {
400 let arena_id = self.arena_id;
401 let idx = self.items.len();
402 A::new_id(arena_id, idx)
405 /// Get a shared reference to the object associated with the given `id` if
408 /// If there is no object associated with `id` (for example, it might
409 /// reference an object allocated within a different arena) then return
413 /// use id_arena::Arena;
415 /// let mut arena = Arena::<usize>::new();
416 /// let id = arena.alloc(42);
417 /// assert!(arena.get(id).is_some());
419 /// let other_arena = Arena::<usize>::new();
420 /// assert!(other_arena.get(id).is_none());
423 pub fn get(&self, id: A::Id) -> Option<&T> {
424 if A::arena_id(id) != self.arena_id {
427 self.items.get(A::index(id))
431 /// Get an exclusive reference to the object associated with the given `id`
434 /// If there is no object associated with `id` (for example, it might
435 /// reference an object allocated within a different arena) then return
439 /// use id_arena::Arena;
441 /// let mut arena = Arena::<usize>::new();
442 /// let id = arena.alloc(42);
443 /// assert!(arena.get_mut(id).is_some());
445 /// let mut other_arena = Arena::<usize>::new();
446 /// assert!(other_arena.get_mut(id).is_none());
449 pub fn get_mut(&mut self, id: A::Id) -> Option<&mut T> {
450 if A::arena_id(id) != self.arena_id {
453 self.items.get_mut(A::index(id))
457 /// Iterate over this arena's items and their ids.
460 /// use id_arena::Arena;
462 /// let mut arena = Arena::<&str>::new();
464 /// arena.alloc("hello");
465 /// arena.alloc("hi");
466 /// arena.alloc("yo");
468 /// for (id, s) in arena.iter() {
469 /// assert_eq!(arena.get(id).unwrap(), s);
470 /// println!("{:?} -> {}", id, s);
474 pub fn iter(&self) -> Iter<T, A> {
475 IntoIterator::into_iter(self)
478 /// Iterate over this arena's items and their ids, allowing mutation of each
481 pub fn iter_mut(&mut self) -> IterMut<T, A> {
482 IntoIterator::into_iter(self)
485 /// Get the number of objects allocated in this arena.
488 /// use id_arena::Arena;
490 /// let mut arena = Arena::<&str>::new();
492 /// arena.alloc("hello");
493 /// arena.alloc("hi");
495 /// assert_eq!(arena.len(), 2);
498 pub fn len(&self) -> usize {
503 impl<T, A> ops::Index<A::Id> for Arena<T, A>
510 fn index(&self, id: A::Id) -> &T {
511 assert_eq!(self.arena_id, A::arena_id(id));
512 &self.items[A::index(id)]
516 impl<T, A> ops::IndexMut<A::Id> for Arena<T, A>
521 fn index_mut(&mut self, id: A::Id) -> &mut T {
522 assert_eq!(self.arena_id, A::arena_id(id));
523 &mut self.items[A::index(id)]
527 fn add_id<A, T>(item: Option<(usize, T)>, arena_id: u32) -> Option<(A::Id, T)>
531 item.map(|(idx, item)| (A::new_id(arena_id, idx), item))
534 /// An iterator over `(Id, &T)` pairs in an arena.
536 /// See [the `Arena::iter()` method](./struct.Arena.html#method.iter) for details.
538 pub struct Iter<'a, T: 'a, A: 'a> {
540 iter: iter::Enumerate<slice::Iter<'a, T>>,
541 _phantom: PhantomData<fn() -> A>,
544 impl<'a, T: 'a, A: 'a> Iterator for Iter<'a, T, A>
548 type Item = (A::Id, &'a T);
551 fn next(&mut self) -> Option<Self::Item> {
552 add_id::<A, _>(self.iter.next(), self.arena_id)
555 fn size_hint(&self) -> (usize, Option<usize>) {
556 self.iter.size_hint()
560 impl<'a, T: 'a, A: 'a> DoubleEndedIterator for Iter<'a, T, A>
564 fn next_back(&mut self) -> Option<Self::Item> {
565 add_id::<A, _>(self.iter.next_back(), self.arena_id)
569 impl<'a, T: 'a, A: 'a> ExactSizeIterator for Iter<'a, T, A>
573 fn len(&self) -> usize {
578 impl<'a, T, A> IntoIterator for &'a Arena<T, A>
582 type Item = (A::Id, &'a T);
583 type IntoIter = Iter<'a, T, A>;
586 fn into_iter(self) -> Iter<'a, T, A> {
588 arena_id: self.arena_id,
589 iter: self.items.iter().enumerate(),
590 _phantom: PhantomData,
595 /// An iterator over `(Id, &mut T)` pairs in an arena.
597 /// See [the `Arena::iter_mut()` method](./struct.Arena.html#method.iter_mut)
600 pub struct IterMut<'a, T: 'a, A: 'a> {
602 iter: iter::Enumerate<slice::IterMut<'a, T>>,
603 _phantom: PhantomData<fn() -> A>,
606 impl<'a, T: 'a, A: 'a> Iterator for IterMut<'a, T, A>
610 type Item = (A::Id, &'a mut T);
613 fn next(&mut self) -> Option<Self::Item> {
614 add_id::<A, _>(self.iter.next(), self.arena_id)
617 fn size_hint(&self) -> (usize, Option<usize>) {
618 self.iter.size_hint()
622 impl<'a, T: 'a, A: 'a> DoubleEndedIterator for IterMut<'a, T, A>
626 fn next_back(&mut self) -> Option<Self::Item> {
627 add_id::<A, _>(self.iter.next_back(), self.arena_id)
631 impl<'a, T: 'a, A: 'a> ExactSizeIterator for IterMut<'a, T, A>
635 fn len(&self) -> usize {
640 impl<'a, T, A> IntoIterator for &'a mut Arena<T, A>
644 type Item = (A::Id, &'a mut T);
645 type IntoIter = IterMut<'a, T, A>;
648 fn into_iter(self) -> IterMut<'a, T, A> {
650 arena_id: self.arena_id,
651 iter: self.items.iter_mut().enumerate(),
652 _phantom: PhantomData,
657 /// An iterator over `(Id, T)` pairs in an arena.
659 pub struct IntoIter<T, A> {
661 iter: iter::Enumerate<vec::IntoIter<T>>,
662 _phantom: PhantomData<fn() -> A>,
665 impl<T, A> Iterator for IntoIter<T, A>
669 type Item = (A::Id, T);
672 fn next(&mut self) -> Option<Self::Item> {
673 add_id::<A, _>(self.iter.next(), self.arena_id)
676 fn size_hint(&self) -> (usize, Option<usize>) {
677 self.iter.size_hint()
681 impl<T, A> DoubleEndedIterator for IntoIter<T, A>
685 fn next_back(&mut self) -> Option<Self::Item> {
686 add_id::<A, _>(self.iter.next_back(), self.arena_id)
690 impl<T, A> ExactSizeIterator for IntoIter<T, A>
694 fn len(&self) -> usize {
699 impl<T, A> IntoIterator for Arena<T, A>
703 type Item = (A::Id, T);
704 type IntoIter = IntoIter<T, A>;
707 fn into_iter(self) -> IntoIter<T, A> {
709 arena_id: self.arena_id,
710 iter: self.items.into_iter().enumerate(),
711 _phantom: PhantomData,
721 fn ids_are_send_sync() {
722 fn assert_send_sync<T: Send + Sync>() {}
724 assert_send_sync::<Id<Foo>>();