1#![cfg_attr(not(feature = "std"), no_std)]
8#![warn(
9 clippy::cast_lossless,
10 clippy::missing_errors_doc,
11 clippy::used_underscore_binding,
12 clippy::redundant_closure_for_method_calls,
13 clippy::type_repetition_in_bounds,
14 clippy::inconsistent_struct_constructor,
15 clippy::default_trait_access,
16 clippy::map_unwrap_or,
17 clippy::items_after_statements
18)]
19#[cfg(not(feature = "std"))]
20#[macro_use]
21extern crate alloc;
22#[cfg(feature = "std")]
23extern crate std as alloc;
24
25mod component_vec;
26mod dedup;
27mod guarded;
28
29#[cfg(test)]
30mod tests;
31
32pub use self::{component_vec::ComponentVec, dedup::DedupArena, guarded::GuardedEntity};
33use alloc::vec::Vec;
34use core::{
35 iter::{DoubleEndedIterator, Enumerate, ExactSizeIterator},
36 marker::PhantomData,
37 ops::{Index, IndexMut},
38 slice,
39};
40
41pub trait ArenaIndex: Copy {
43 fn into_usize(self) -> usize;
45 fn from_usize(value: usize) -> Self;
47}
48
49#[derive(Debug, Clone)]
53pub struct Arena<Idx, T> {
54 entities: Vec<T>,
55 marker: PhantomData<Idx>,
56}
57
58unsafe impl<Idx, T> Send for Arena<Idx, T> where T: Send {}
60
61unsafe impl<Idx, T> Sync for Arena<Idx, T> where T: Send {}
63
64impl<Idx, T> Default for Arena<Idx, T> {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl<Idx, T> PartialEq for Arena<Idx, T>
71where
72 T: PartialEq,
73{
74 fn eq(&self, other: &Self) -> bool {
75 self.entities.eq(&other.entities)
76 }
77}
78
79impl<Idx, T> Eq for Arena<Idx, T> where T: Eq {}
80
81impl<Idx, T> Arena<Idx, T> {
82 pub fn new() -> Self {
84 Self {
85 entities: Vec::new(),
86 marker: PhantomData,
87 }
88 }
89
90 #[inline]
92 pub fn len(&self) -> usize {
93 self.entities.len()
94 }
95
96 #[inline]
98 pub fn is_empty(&self) -> bool {
99 self.len() == 0
100 }
101
102 pub fn clear(&mut self) {
104 self.entities.clear();
105 }
106
107 pub fn iter(&self) -> Iter<Idx, T> {
109 Iter {
110 iter: self.entities.iter().enumerate(),
111 marker: PhantomData,
112 }
113 }
114
115 pub fn iter_mut(&mut self) -> IterMut<Idx, T> {
117 IterMut {
118 iter: self.entities.iter_mut().enumerate(),
119 marker: PhantomData,
120 }
121 }
122}
123
124impl<Idx, T> Arena<Idx, T>
125where
126 Idx: ArenaIndex,
127{
128 fn next_index(&self) -> Idx {
130 Idx::from_usize(self.entities.len())
131 }
132
133 #[inline]
135 pub fn alloc(&mut self, entity: T) -> Idx {
136 let index = self.next_index();
137 self.entities.push(entity);
138 index
139 }
140
141 #[inline]
143 pub fn get(&self, index: Idx) -> Option<&T> {
144 self.entities.get(index.into_usize())
145 }
146
147 #[inline]
149 pub fn get_mut(&mut self, index: Idx) -> Option<&mut T> {
150 self.entities.get_mut(index.into_usize())
151 }
152}
153
154impl<Idx, T> FromIterator<T> for Arena<Idx, T> {
155 fn from_iter<I>(iter: I) -> Self
156 where
157 I: IntoIterator<Item = T>,
158 {
159 Self {
160 entities: Vec::from_iter(iter),
161 marker: PhantomData,
162 }
163 }
164}
165
166impl<'a, Idx, T> IntoIterator for &'a Arena<Idx, T>
167where
168 Idx: ArenaIndex,
169{
170 type Item = (Idx, &'a T);
171 type IntoIter = Iter<'a, Idx, T>;
172
173 fn into_iter(self) -> Self::IntoIter {
174 self.iter()
175 }
176}
177
178impl<'a, Idx, T> IntoIterator for &'a mut Arena<Idx, T>
179where
180 Idx: ArenaIndex,
181{
182 type Item = (Idx, &'a mut T);
183 type IntoIter = IterMut<'a, Idx, T>;
184
185 fn into_iter(self) -> Self::IntoIter {
186 self.iter_mut()
187 }
188}
189
190#[derive(Debug)]
192pub struct Iter<'a, Idx, T> {
193 iter: Enumerate<slice::Iter<'a, T>>,
194 marker: PhantomData<fn() -> Idx>,
195}
196
197impl<'a, Idx, T> Iterator for Iter<'a, Idx, T>
198where
199 Idx: ArenaIndex,
200{
201 type Item = (Idx, &'a T);
202
203 #[inline]
204 fn next(&mut self) -> Option<Self::Item> {
205 self.iter
206 .next()
207 .map(|(idx, entity)| (Idx::from_usize(idx), entity))
208 }
209
210 #[inline]
211 fn size_hint(&self) -> (usize, Option<usize>) {
212 self.iter.size_hint()
213 }
214}
215
216impl<'a, Idx, T> DoubleEndedIterator for Iter<'a, Idx, T>
217where
218 Idx: ArenaIndex,
219{
220 #[inline]
221 fn next_back(&mut self) -> Option<Self::Item> {
222 self.iter
223 .next()
224 .map(|(idx, entity)| (Idx::from_usize(idx), entity))
225 }
226}
227
228impl<'a, Idx, T> ExactSizeIterator for Iter<'a, Idx, T>
229where
230 Idx: ArenaIndex,
231{
232 fn len(&self) -> usize {
233 self.iter.len()
234 }
235}
236
237#[derive(Debug)]
239pub struct IterMut<'a, Idx, T> {
240 iter: Enumerate<slice::IterMut<'a, T>>,
241 marker: PhantomData<fn() -> Idx>,
242}
243
244impl<'a, Idx, T> Iterator for IterMut<'a, Idx, T>
245where
246 Idx: ArenaIndex,
247{
248 type Item = (Idx, &'a mut T);
249
250 #[inline]
251 fn next(&mut self) -> Option<Self::Item> {
252 self.iter
253 .next()
254 .map(|(idx, entity)| (Idx::from_usize(idx), entity))
255 }
256
257 #[inline]
258 fn size_hint(&self) -> (usize, Option<usize>) {
259 self.iter.size_hint()
260 }
261}
262
263impl<'a, Idx, T> DoubleEndedIterator for IterMut<'a, Idx, T>
264where
265 Idx: ArenaIndex,
266{
267 #[inline]
268 fn next_back(&mut self) -> Option<Self::Item> {
269 self.iter
270 .next()
271 .map(|(idx, entity)| (Idx::from_usize(idx), entity))
272 }
273}
274
275impl<'a, Idx, T> ExactSizeIterator for IterMut<'a, Idx, T>
276where
277 Idx: ArenaIndex,
278{
279 #[inline]
280 fn len(&self) -> usize {
281 self.iter.len()
282 }
283}
284
285impl<Idx, T> Arena<Idx, T> {
286 fn index_out_of_bounds(len: usize, index: usize) -> ! {
288 panic!("index out of bounds: the len is {len} but the index is {index}")
289 }
290}
291
292impl<Idx, T> Index<Idx> for Arena<Idx, T>
293where
294 Idx: ArenaIndex,
295{
296 type Output = T;
297
298 #[inline]
299 fn index(&self, index: Idx) -> &Self::Output {
300 self.get(index)
301 .unwrap_or_else(|| Self::index_out_of_bounds(self.len(), index.into_usize()))
302 }
303}
304
305impl<Idx, T> IndexMut<Idx> for Arena<Idx, T>
306where
307 Idx: ArenaIndex,
308{
309 #[inline]
310 fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
311 let len = self.len();
312 self.get_mut(index)
313 .unwrap_or_else(|| Self::index_out_of_bounds(len, index.into_usize()))
314 }
315}