1#[cfg(not(feature = "std"))]
2extern crate alloc;
3
4#[cfg(feature = "std")]
5extern crate core;
6
7#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9use core::{
10 cell::{
11 RefCell,
12 RefMut,
13 },
14 cmp,
15 iter,
16 mem,
17 slice,
18 str,
19};
20
21const MIN_CAPACITY: usize = 1;
22const DEFAULT_INITIAL_SIZE: usize = 1024;
23
24pub struct Arena<T> {
42 blocks: RefCell<MemoryBlocks<T>>,
43}
44
45struct MemoryBlocks<T> {
48 current: Vec<T>,
49 committed: Vec<Vec<T>>,
50}
51
52impl<T> MemoryBlocks<T> {
53 fn remaining_space_in_current_block(&self) -> usize {
54 self.current.capacity() - self.current.len()
55 }
56
57 #[inline(never)]
58 #[cold]
59 fn reserve(&mut self, num: usize) {
60 let double = self
61 .current
62 .capacity()
63 .checked_mul(2)
64 .expect("capacity overflow");
65 let required = num.checked_next_power_of_two().expect("capacity overflow");
66 let new_capacity = cmp::max(double, required);
67 if self.current.is_empty() {
68 self.current.reserve(new_capacity);
70 } else {
71 self.committed.push(mem::replace(
73 &mut self.current,
74 Vec::with_capacity(new_capacity),
75 ));
76 }
77 }
78}
79
80enum IterMutState<'a, T> {
81 Committed {
82 index: usize,
83 iter: slice::IterMut<'a, T>,
84 },
85 Current {
86 iter: slice::IterMut<'a, T>,
87 },
88}
89
90pub struct IterMut<'a, T> {
92 blocks: RefMut<'a, MemoryBlocks<T>>,
93 state: IterMutState<'a, T>,
94}
95
96impl<'a, T> Iterator for IterMut<'a, T> {
97 type Item = &'a mut T;
98
99 fn next(&mut self) -> Option<Self::Item> {
100 loop {
101 self.state = match self.state {
102 IterMutState::Committed {
103 mut index,
104 ref mut iter,
105 } => match iter.next() {
106 Some(item) => return Some(item),
107 None => {
108 index += 1;
109 if index < self.blocks.committed.len() {
110 let iter = self.blocks.committed[index].iter_mut();
111 let iter = unsafe { mem::transmute(iter) };
112 IterMutState::Committed { index, iter }
113 } else {
114 let iter = self.blocks.current.iter_mut();
115 let iter = unsafe { mem::transmute(iter) };
116 IterMutState::Current { iter }
117 }
118 }
119 },
120 IterMutState::Current { ref mut iter } => return iter.next(),
121 }
122 }
123 }
124
125 fn size_hint(&self) -> (usize, Option<usize>) {
126 match &self.state {
127 IterMutState::Committed { index, iter } => {
128 let next = index + 1;
129 let known_remainder = self.blocks.current.len()
130 + if next < self.blocks.committed.len() {
131 self.blocks.committed[next..]
132 .iter()
133 .fold(0, |acc, b| acc + b.len())
134 } else {
135 0
136 };
137 let (min, max) = iter.size_hint();
138 return (known_remainder + min, max.map(|n| n + known_remainder));
139 }
140 IterMutState::Current { iter } => iter.size_hint(),
141 }
142 }
143}
144
145impl<T> Arena<T> {
146 pub fn new() -> Self {
148 let size = cmp::max(1, mem::size_of::<T>());
149 Self::with_capacity(DEFAULT_INITIAL_SIZE / size)
150 }
151
152 pub fn with_capacity(size: usize) -> Self {
154 let size = cmp::max(MIN_CAPACITY, size);
155 Self {
156 blocks: RefCell::new(MemoryBlocks {
157 current: Vec::with_capacity(size),
158 committed: Vec::new(),
159 }),
160 }
161 }
162
163 pub fn is_empty(&self) -> bool {
165 self.len() == 0
166 }
167
168 pub fn len(&self) -> usize {
170 let blocks = self.blocks.borrow();
171 blocks
172 .committed
173 .iter()
174 .fold(blocks.current.len(), |acc, b| acc + b.len())
175 }
176
177 pub fn alloc(&self, value: T) -> &mut T {
179 self.alloc_in_current_block(value)
180 .unwrap_or_else(|value| self.alloc_in_new_block(value))
181 }
182
183 #[inline]
184 fn alloc_in_current_block(&self, value: T) -> Result<&mut T, T> {
185 let mut blocks = self.blocks.borrow_mut();
186 let len = blocks.current.len();
187 if blocks.current.len() < blocks.current.capacity() {
188 blocks.current.push(value);
189 Ok(unsafe { &mut *blocks.current.as_mut_ptr().add(len) })
190 } else {
191 Err(value)
193 }
194 }
195
196 fn alloc_in_new_block(&self, value: T) -> &mut T {
197 &mut self.alloc_extend(iter::once(value))[0]
198 }
199
200 pub fn alloc_extend<I>(&self, iterable: I) -> &mut [T]
204 where
205 I: IntoIterator<Item = T>,
206 {
207 let mut blocks = self.blocks.borrow_mut();
208 let mut iter = iterable.into_iter();
209 let mut slice_start_index = 0;
211 let min_size = iter.size_hint().0;
214 if min_size > blocks.remaining_space_in_current_block() {
215 blocks.reserve(min_size);
216 blocks.current.extend(iter);
217 } else {
218 slice_start_index = blocks.current.len();
222 let mut i = 0;
223 while let Some(value) = iter.next() {
224 if blocks.current.len() == blocks.current.capacity() {
225 let blocks = &mut *blocks;
227 blocks.reserve(i + 1);
228 let prev = blocks.committed.last_mut().unwrap();
230 let prev_len = prev.len();
231 blocks.current.extend(prev.drain(prev_len - i..));
232 blocks.current.push(value);
233 blocks.current.extend(iter);
234 slice_start_index = 0;
235 break;
236 }
237 blocks.current.push(value);
238 i += 1;
239 }
240 }
241
242 unsafe {
245 let slice_len = blocks.current.len() - slice_start_index;
246 slice::from_raw_parts_mut(
247 blocks.current.as_mut_ptr().add(slice_start_index),
248 slice_len,
249 )
250 }
251 }
252
253 pub fn reserve(&self, additional: usize) {
255 let mut blocks = self.blocks.borrow_mut();
256
257 if additional > blocks.remaining_space_in_current_block() {
258 blocks.reserve(additional);
259 }
260 }
261
262 pub fn into_vec(self) -> Vec<T> {
266 let mut blocks = self.blocks.into_inner();
267 let mut out = Vec::with_capacity(
268 blocks
269 .committed
270 .iter()
271 .fold(blocks.current.len(), |acc, b| acc + b.len()),
272 );
273 for mut block in blocks.committed {
274 out.append(&mut block);
275 }
276 out.append(&mut blocks.current);
277 out
278 }
279
280 pub fn iter_mut(&mut self) -> IterMut<T> {
287 let mut blocks = self.blocks.borrow_mut();
288 let state = if !blocks.committed.is_empty() {
289 let index = 0;
290 let iter = blocks.committed[index].iter_mut();
291 let iter = unsafe { mem::transmute(iter) };
292 IterMutState::Committed { index, iter }
293 } else {
294 let iter = unsafe { mem::transmute(blocks.current.iter_mut()) };
295 IterMutState::Current { iter }
296 };
297 IterMut { blocks, state }
298 }
299}
300
301impl Arena<u8> {
302 pub fn alloc_str(&self, s: &str) -> &mut str {
304 let slice = self.alloc_extend(s.bytes());
305 unsafe { str::from_utf8_unchecked_mut(slice) }
307 }
308}
309
310impl<T> Default for Arena<T> {
311 fn default() -> Self {
312 Self::new()
313 }
314}
315
316impl<A> FromIterator<A> for Arena<A> {
317 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
318 let iter = iter.into_iter();
319 let arena = Self::with_capacity(iter.size_hint().0);
320 arena.alloc_extend(iter);
321 arena
322 }
323}
324
325#[cfg(test)]
326mod arena_test {
327 #[cfg(not(feature = "std"))]
328 extern crate alloc;
329
330 #[cfg(not(feature = "std"))]
331 use alloc::vec;
332 use core::{
333 cell::Cell,
334 mem,
335 };
336 #[cfg(feature = "std")]
337 use std::sync::{
338 Arc,
339 Mutex,
340 };
341
342 use crate::Arena;
343
344 struct DropCounter<'c>(&'c Cell<u32>);
346
347 impl<'c> Drop for DropCounter<'c> {
348 fn drop(&mut self) {
349 self.0.set(self.0.get() + 1);
350 }
351 }
352
353 struct Node<'a, 'd, T> {
357 parent: Option<&'a Node<'a, 'd, T>>,
358 value: T,
359 #[allow(dead_code)]
360 drop_counter: DropCounter<'d>,
361 }
362
363 impl<'a, 'd, T> Node<'a, 'd, T> {
364 pub fn new(
365 parent: Option<&'a Node<'a, 'd, T>>,
366 value: T,
367 drop_counter: DropCounter<'d>,
368 ) -> Self {
369 Self {
370 parent,
371 value,
372 drop_counter,
373 }
374 }
375 }
376
377 fn commited_blocks<T>(arena: &Arena<T>) -> usize {
378 arena.blocks.borrow().committed.len()
379 }
380
381 #[test]
382 #[allow(dropping_references)]
383 fn allocates_and_owns_values() {
384 let drop_counter = Cell::new(0);
385 {
386 let arena = Arena::with_capacity(2);
387 assert!(arena.is_empty());
388
389 let mut node: &Node<u32> = arena.alloc(Node::new(None, 1, DropCounter(&drop_counter)));
391 assert_eq!(commited_blocks(&arena), 0);
392 assert_eq!(arena.len(), 1);
393 assert!(!arena.is_empty());
394 node = arena.alloc(Node::new(Some(node), 2, DropCounter(&drop_counter)));
395 assert_eq!(commited_blocks(&arena), 0);
396 assert_eq!(arena.len(), 2);
397 node = arena.alloc(Node::new(Some(node), 3, DropCounter(&drop_counter)));
398 assert_eq!(commited_blocks(&arena), 1);
399 assert_eq!(arena.len(), 3);
400 node = arena.alloc(Node::new(Some(node), 4, DropCounter(&drop_counter)));
401 assert_eq!(commited_blocks(&arena), 1);
402 assert_eq!(arena.len(), 4);
403
404 assert_eq!(node.value, 4);
405 assert_eq!(node.parent.unwrap().value, 3);
406 assert_eq!(node.parent.unwrap().parent.unwrap().value, 2);
407 assert_eq!(
408 node.parent.unwrap().parent.unwrap().parent.unwrap().value,
409 1
410 );
411 assert!(node
412 .parent
413 .unwrap()
414 .parent
415 .unwrap()
416 .parent
417 .unwrap()
418 .parent
419 .is_none());
420
421 mem::drop(node);
424 assert_eq!(drop_counter.get(), 0);
425
426 node = arena.alloc(Node::new(None, 5, DropCounter(&drop_counter)));
427 assert_eq!(commited_blocks(&arena), 1);
428 node = arena.alloc(Node::new(Some(node), 6, DropCounter(&drop_counter)));
429 assert_eq!(commited_blocks(&arena), 1);
430 node = arena.alloc(Node::new(Some(node), 7, DropCounter(&drop_counter)));
431 assert_eq!(commited_blocks(&arena), 2);
432
433 assert_eq!(node.value, 7);
434 assert_eq!(node.parent.unwrap().value, 6);
435 assert_eq!(node.parent.unwrap().parent.unwrap().value, 5);
436 assert!(node.parent.unwrap().parent.unwrap().parent.is_none());
437
438 assert_eq!(drop_counter.get(), 0);
439 }
440 assert_eq!(drop_counter.get(), 7);
442 }
443
444 #[test]
445 #[cfg(feature = "std")]
446 fn allocates_strings() {
447 let arena = Arena::new();
448 let str = arena.alloc_str("abcd");
449 assert_eq!(str, "abcd");
450 let str = arena.alloc_str("defg");
451 assert_eq!(str, "defg");
452 let str = "hijklmnop".to_owned();
453 let str = arena.alloc_str(&str);
454 assert_eq!(str, "hijklmnop");
455 }
456
457 #[test]
458 fn supports_circular_reference() {
459 struct CircularNode<'a, T> {
460 value: T,
461 other: Cell<Option<&'a CircularNode<'a, T>>>,
462 }
463
464 let arena = Arena::with_capacity(2);
465 let a = arena.alloc(CircularNode {
466 value: 1,
467 other: Cell::new(None),
468 });
469 let b = arena.alloc(CircularNode {
470 value: 2,
471 other: Cell::new(None),
472 });
473 a.other.set(Some(b));
474 b.other.set(Some(a));
475 assert_eq!(a.other.get().unwrap().value, 2);
476 assert_eq!(b.other.get().unwrap().value, 1);
477 }
478
479 #[test]
480 fn alloc_extend_allocates_and_returns_slice() {
481 let arena = Arena::with_capacity(2);
482 for i in 0..15 {
483 let slice = arena.alloc_extend(0..i);
484 for (j, &value) in (0..i).zip(slice.iter()) {
485 assert_eq!(j, value)
486 }
487 }
488 }
489
490 #[test]
491 fn alloc_extend_allocates_and_owns_values() {
492 let drop_counter = Cell::new(0);
493 {
494 let arena = Arena::with_capacity(2);
495 let iter = (0..100).map(|i| Node::new(None, i, DropCounter(&drop_counter)));
496 let root = &arena.alloc_extend(iter)[0];
497 let iter = (0..100).map(|i| Node::new(Some(root), i, DropCounter(&drop_counter)));
498 arena.alloc_extend(iter);
499 assert_eq!(drop_counter.get(), 0);
500 }
501 assert_eq!(drop_counter.get(), 200);
502 }
503
504 #[test]
505 fn alloc_extend_uses_size_hint() {
506 struct Iter<I>(I);
507 impl<I> Iterator for Iter<I>
508 where
509 I: Iterator,
510 {
511 type Item = I::Item;
512
513 fn next(&mut self) -> Option<Self::Item> {
514 self.0.next()
515 }
516
517 fn size_hint(&self) -> (usize, Option<usize>) {
518 (16, None)
519 }
520 }
521
522 let arena = Arena::with_capacity(10);
523 arena.alloc(123);
524 let slice = arena.alloc_extend(Iter(0..4));
527 assert_eq!(commited_blocks(&arena), 1);
528 assert_eq!(slice.len(), 4);
529 }
530
531 #[test]
532 fn alloc_extend_ignores_size_hint() {
533 struct Iter<I>(I);
534 impl<I> Iterator for Iter<I>
535 where
536 I: Iterator,
537 {
538 type Item = I::Item;
539
540 fn next(&mut self) -> Option<Self::Item> {
541 self.0.next()
542 }
543
544 fn size_hint(&self) -> (usize, Option<usize>) {
545 (2, None)
546 }
547 }
548
549 let arena = Arena::with_capacity(50);
550 arena.alloc(123);
551 let slice = arena.alloc_extend(Iter(0..100));
556 assert_eq!(commited_blocks(&arena), 1);
557 assert_eq!(slice.len(), 100);
558 }
559
560 #[test]
561 fn alloc_respects_initial_capacity() {
562 let arena = Arena::with_capacity(1000);
563 arena.alloc_extend(0..1000);
564 assert_eq!(commited_blocks(&arena), 0);
565 }
566
567 #[test]
568 fn reserve_large_block() {
569 let arena = Arena::with_capacity(2);
570 arena.alloc_extend(0..1);
572 arena.alloc_extend(0..100);
573 arena.reserve(1000);
575 assert_eq!(commited_blocks(&arena), 2);
576 arena.alloc_extend(0..500);
578 arena.alloc_extend(501..1000);
579 assert_eq!(commited_blocks(&arena), 2);
580 }
581
582 #[test]
583 fn into_vec_reflects_insertion_order() {
584 let arena = Arena::with_capacity(1);
585 for &s in &["a", "b", "c", "d"] {
586 arena.alloc(s);
587 }
588 let vec = arena.into_vec();
589 assert_eq!(vec, vec!["a", "b", "c", "d"])
590 }
591
592 #[test]
593 fn iter_mut_itereates_in_order() {
594 #[derive(Debug, PartialEq, Eq)]
595 struct NoCopy(usize);
596
597 let mut arena = Arena::new();
598 for i in 0..10 {
599 arena.alloc(NoCopy(i));
600 }
601 assert!(arena
602 .iter_mut()
603 .zip((0..10).map(|i| NoCopy(i)))
604 .all(|(a, b)| a == &b));
605 }
606
607 #[test]
608 fn iter_mut_allows_mutable_access() {
609 let mut arena = Arena::new();
610 for i in 0..10 {
611 arena.alloc(i);
612 }
613 for i in arena.iter_mut() {
614 *i += 1
615 }
616 assert!(arena.iter_mut().zip(1..11).all(|(a, b)| a == &b));
617 }
618
619 #[test]
620 fn iter_mut_over_multiple_blocks() {
621 const LENGTH: usize = 1000;
622 const CAPACITY: usize = 4;
623
624 let mut arena = Arena::with_capacity(CAPACITY);
625 for i in 0..LENGTH {
626 arena.alloc(i);
627 }
628
629 assert!(commited_blocks(&arena) > 1);
630 assert_eq!(arena.len(), LENGTH);
631 assert!(arena.iter_mut().zip(0..LENGTH).all(|(a, b)| a == &b));
632 }
633
634 #[test]
635 fn iter_mut_over_one_block() {
636 const LENGTH: usize = 1000;
637 const CAPACITY: usize = 10000;
638
639 let mut arena = Arena::with_capacity(CAPACITY);
640 for i in 0..LENGTH {
641 arena.alloc(i);
642 }
643
644 assert_eq!(commited_blocks(&arena), 0);
645 assert_eq!(arena.len(), LENGTH);
646 assert!(arena.iter_mut().zip(0..LENGTH).all(|(a, b)| a == &b));
647 }
648
649 #[test]
650 fn iter_mut_size_hint_is_always_bounded_correctly() {
651 const LENGTH: usize = 1000;
652
653 let mut arena = Arena::with_capacity(0);
654 for i in 0..LENGTH {
655 arena.alloc(i);
656 }
657 let mut iter = arena.iter_mut().zip((0..LENGTH).rev());
658 while let Some((_, remaining)) = iter.next() {
659 let (min, max) = iter.size_hint();
660 assert!(min <= remaining);
661 if let Some(max) = max {
662 assert!(max >= remaining)
663 }
664 }
665 }
666
667 #[test]
668 fn constructible_from_iterator() {
669 let arena: Arena<i32> = (0..100).collect();
670 assert_eq!(arena.len(), 100);
671 }
672
673 #[test]
674 #[cfg(feature = "std")]
675 fn arena_is_send() {
676 let arena: Arena<i32> = (0..100).collect();
677
678 let arena = Arc::new(Mutex::new(arena));
679
680 let f = |arena: Arc<Mutex<Arena<i32>>>| {
681 move || {
682 arena.lock().unwrap().alloc_extend(100..200);
683 }
684 };
685 std::thread::spawn(f(arena.clone())).join().unwrap();
686
687 assert_eq!(arena.lock().unwrap().len(), 200);
688 }
689}