Skip to content

Commit 7c4fc0c

Browse files
committed
Replace specific Arena constructors with generic one
1 parent 02126cd commit 7c4fc0c

File tree

5 files changed

+51
-287
lines changed

5 files changed

+51
-287
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
- Redefine `ArenaStorage` as a struct for compatibility with non-array-like layouts
1212
- Remove `HeapStorage` type alias and add `AllocStorage` struct (similar to `ArenaStorage`)
1313
- Rename `Arena::{collect, try_collect}` to `Arena::{collect_slice, try_collect_slice}`
14+
- Remove `Arena::{try_vec, try_deque, try_heap, vec, deque, heap}` in favor of
15+
the generic `Arena::{try_with_capacity, with_capacity}`
1416

1517
[storage-abstraction-v2]: https://gist.github.com/teryror/7b9a23fd0cd8dcfbcb6ebd34ee2639f8
1618

@@ -25,7 +27,7 @@
2527
- Implement `Vec::drain_filter` and `Vec::drain_filter_range`
2628
- New methods `Deque::force_push_front` and `Deque::force_push_back`
2729
for using `Deque` as a classic ring buffer
28-
- New methods `Arena::with_capacity` for ergonomically constructing arenas when
30+
- New methods `Arena::static_with_capacity` for ergonomically constructing arenas when
2931
the `alloc` crate is available, and `Arena::{collect_with_capacity, try_collect_with_capacity}`,
3032
which more closely approximate `Iterator::collect` than the old `collect` methods
3133
- Add support for multiple type declarations in a single `index_type!` invocation

src/arena.rs

+29-267
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,13 @@
5858
//! This does not apply to creating sub-arenas.
5959
6060
use crate::cache::CacheTable;
61-
use crate::pool::direct::DirectArenaPool;
62-
use crate::pool::Handle;
63-
use crate::pool::packed::PackedArenaPool;
6461
use crate::storage::{ArenaStorage, ArrayLike, Capacity, LayoutSpec};
6562
use crate::string::ArenaString;
66-
use crate::vec::ArenaVec;
67-
use crate::{binary_heap::ArenaHeap, ArenaDeque};
6863

6964
use core::alloc::Layout;
7065
use core::cmp::Ordering;
7166
use core::fmt::{self, Debug, Display, Formatter, Pointer, Write};
72-
use core::hash::{BuildHasher, BuildHasherDefault, Hash, Hasher};
67+
use core::hash::{BuildHasher, Hash, Hasher};
7368
use core::marker::PhantomData;
7469
use core::mem::MaybeUninit;
7570
use core::ops::{Deref, DerefMut, Range};
@@ -407,7 +402,7 @@ impl Arena<'static> {
407402
/// # fn test() -> Option<()> {
408403
/// # let ptr;
409404
/// {
410-
/// let mut arena = coca::Arena::try_with_capacity(1024 * 1024)?;
405+
/// let mut arena = coca::Arena::try_static_with_capacity(1024 * 1024)?;
411406
/// # ptr = arena.alloc(()).as_mut() as *mut () as *mut u8;
412407
/// let hello = coca::fmt!(arena, "{}, {}!", "Hello", "World")?;
413408
/// assert_eq!(hello.as_ref(), "Hello, World!");
@@ -421,7 +416,7 @@ impl Arena<'static> {
421416
/// # test().unwrap();
422417
/// ```
423418
#[inline]
424-
pub fn try_with_capacity(capacity: usize) -> Option<Self> {
419+
pub fn try_static_with_capacity(capacity: usize) -> Option<Self> {
425420
unsafe {
426421
let ptr = alloc::alloc::alloc(Layout::from_size_align(capacity, 8).ok()?);
427422
if ptr.is_null() { return None; }
@@ -438,8 +433,8 @@ impl Arena<'static> {
438433
/// Panics if the heap allocation fails.
439434
#[inline]
440435
#[track_caller]
441-
pub fn with_capacity(capacity: usize) -> Self {
442-
Self::try_with_capacity(capacity).expect("unexpected allocation failure in `Arena::with_capacity`")
436+
pub fn static_with_capacity(capacity: usize) -> Self {
437+
Self::try_static_with_capacity(capacity).expect("unexpected allocation failure in `Arena::static_with_capacity`")
443438
}
444439
}
445440

@@ -920,84 +915,41 @@ impl<'src> Arena<'src> {
920915
self.try_reserve_array(count).map(|b| b.init_with(|_| x))
921916
}
922917

923-
/// Constructs a [`ArenaVec`] with the given capacity.
924-
///
925-
/// # Panics
926-
/// Panics if the specified capacity cannot be represented by a `usize`, or
927-
/// if the remaining space in the arena is insufficient. See
928-
/// [`try_vec`](Arena::try_vec) for a checked version.
929-
#[track_caller]
930-
pub fn vec<T, I: Capacity>(&mut self, capacity: I) -> ArenaVec<'src, T, I> {
931-
self.try_vec(capacity)
932-
.expect("unexpected allocation failure in `vec`")
933-
}
934-
935-
/// Constructs an [`ArenaVec`] with the given capacity.
936-
///
937-
/// Returns [`None`] if the remaining space in the arena is insufficient.
938-
///
939-
/// # Panics
940-
/// Panics if the specified capacity cannot be represented by a `usize`.
941-
///
942-
/// # Examples
943-
/// ```
944-
/// use coca::Arena;
945-
/// use core::mem::MaybeUninit;
946-
///
947-
/// # fn test() -> Option<()> {
948-
/// let mut backing_region = [MaybeUninit::uninit(); 1024];
949-
/// let mut arena = Arena::from(&mut backing_region[..]);
950-
///
951-
/// let mut squares = arena.try_vec::<i64, usize>(100)?;
952-
/// assert!(arena.try_vec::<i64, usize>(100).is_none());
953-
///
954-
/// assert_eq!(squares.len(), 0);
955-
/// assert_eq!(squares.capacity(), 100);
956-
///
957-
/// for x in 1..=100 { squares.push(x * x) }
958-
/// assert_eq!(&squares[..8], &[1, 4, 9, 16, 25, 36, 49, 64]);
959-
/// # Some(())
960-
/// # }
961-
/// # assert!(test().is_some());
962-
/// ```
963-
pub fn try_vec<T, I: Capacity>(&mut self, capacity: I) -> Option<ArenaVec<'src, T, I>> {
964-
let storage = self.try_storage_with_capacity(capacity.as_usize())?;
965-
Some(ArenaVec::<T, I>::from(storage))
966-
}
967-
968-
/// Constructs an [`ArenaString`] with the given capacity.
918+
/// Constructs a collection `C` with the given capacity, backed by arena-allocated memory.
969919
///
970920
/// # Panics
971-
/// Panics if the remaining space in the arena is insufficient.
972-
/// See [`try_string`](Arena::try_string) for a checked version that never panics.
973-
#[track_caller]
974-
pub fn string<I: Capacity>(&mut self, capacity: I) -> ArenaString<'src, I> {
975-
self.try_string(capacity).expect("unexpected allocation failure in `string`")
921+
/// Panics if the remaining space is insufficient.
922+
/// See [`try_with_capacity`](Arena::try_with_capacity) for a checked version
923+
/// that never panics.
924+
pub fn with_capacity<S, C>(&mut self, capacity: usize) -> C
925+
where
926+
C: From<ArenaStorage<'src, S>>,
927+
S: LayoutSpec,
928+
{
929+
self.try_with_capacity(capacity).expect("unexpected allocation failure in `with_capacity`")
976930
}
977931

978-
/// Constructs an [`ArenaString`] with the given capacity.
932+
/// Constructs a collection `C` with the given capacity, backed by arena-allocated memory.
979933
///
980-
/// Returns [`None`] if the remaining space in the arena is insufficient.
934+
/// Returns [`None`] if the remaining space is insufficient.
981935
///
982936
/// # Examples
983937
/// ```
984-
/// use coca::Arena;
938+
/// use coca::{Arena, ArenaVec};
985939
/// use core::mem::MaybeUninit;
986940
///
987-
/// # fn test() -> Option<()> {
988941
/// let mut backing_region = [MaybeUninit::uninit(); 1024];
989942
/// let mut arena = Arena::from(&mut backing_region[..]);
990-
///
991-
/// let mut s = arena.try_string(100usize)?;
992-
/// s.push_str("Hello, ");
993-
/// s.push_str("World!");
994-
/// assert_eq!(s, "Hello, World!");
995-
/// # Some(()) }
996-
/// # assert!(test().is_some());
943+
///
944+
/// let v: ArenaVec<'_, i64, usize> = arena.try_with_capacity(100).unwrap();
945+
/// assert!(arena.try_with_capacity::<_, ArenaVec<'_, i64, usize>>(100).is_none());
997946
/// ```
998-
pub fn try_string<I: Capacity>(&mut self, capacity: I) -> Option<ArenaString<'src, I>> {
999-
let storage = self.try_storage_with_capacity(capacity.as_usize())?;
1000-
Some(ArenaString::from(storage))
947+
pub fn try_with_capacity<S, C>(&mut self, capacity: usize) -> Option<C>
948+
where
949+
C: From<ArenaStorage<'src, S>>,
950+
S: LayoutSpec,
951+
{
952+
Some(C::from(self.try_storage_with_capacity(capacity)?))
1001953
}
1002954

1003955
/// Constructs an [`ArenaString`] initialized with the given contents, and no excess capacity.
@@ -1031,7 +983,7 @@ impl<'src> Arena<'src> {
1031983
/// ```
1032984
pub fn try_string_from<I: Capacity, T: AsRef<str>>(&mut self, value: T) -> Option<ArenaString<'src, I>> {
1033985
let str = value.as_ref();
1034-
let mut result = self.try_string(I::from_usize(str.len()))?;
986+
let mut result: ArenaString<'_, _> = self.try_with_capacity(str.len())?;
1035987
result.push_str(str);
1036988
Some(result)
1037989
}
@@ -1074,190 +1026,11 @@ impl<'src> Arena<'src> {
10741026
return None;
10751027
}
10761028

1077-
let mut result = self.try_string(capacity)?;
1029+
let mut result: ArenaString<'_, _> = self.try_with_capacity(capacity.as_usize())?;
10781030
result.push_str(value.as_ref());
10791031
Some(result)
10801032
}
10811033

1082-
/// Constructs a [`ArenaHeap`] with the given capacity.
1083-
///
1084-
/// # Panics
1085-
/// Panics if the specified capacity cannot be represented by a `usize`, or
1086-
/// if the remaining space in the arena is insufficient. See
1087-
/// [`try_heap`](Arena::try_heap) for a checked version.
1088-
#[track_caller]
1089-
pub fn heap<T: Ord, I: Capacity>(&mut self, capacity: I) -> ArenaHeap<'src, T, I> {
1090-
self.try_heap(capacity)
1091-
.expect("unexpected allocation failure in `heap`")
1092-
}
1093-
1094-
/// Constructs an [`ArenaHeap`] with the given capacity.
1095-
///
1096-
/// Returns [`None`] if the remaining space in the arena is insufficient.
1097-
///
1098-
/// # Panics
1099-
/// Panics if the specified capacity cannot be represented by a `usize`.
1100-
///
1101-
/// # Examples
1102-
/// ```
1103-
/// use coca::Arena;
1104-
/// use core::mem::MaybeUninit;
1105-
///
1106-
/// # fn test() -> Option<()> {
1107-
/// let mut backing_region = [MaybeUninit::uninit(); 1024];
1108-
/// let mut arena = Arena::from(&mut backing_region[..]);
1109-
///
1110-
/// let mut heap = arena.try_heap::<i64, usize>(100)?;
1111-
/// assert!(arena.try_heap::<i64, usize>(100).is_none());
1112-
///
1113-
/// assert_eq!(heap.len(), 0);
1114-
/// assert_eq!(heap.capacity(), 100);
1115-
///
1116-
/// for x in 1..=100 { heap.push(x) }
1117-
/// for x in (1..=100).rev() {
1118-
/// assert_eq!(heap.pop(), Some(x));
1119-
/// }
1120-
/// # Some(())
1121-
/// # }
1122-
/// # assert!(test().is_some());
1123-
/// ```
1124-
pub fn try_heap<T: Ord, I: Capacity>(&mut self, capacity: I) -> Option<ArenaHeap<'src, T, I>> {
1125-
let storage = self.try_storage_with_capacity(capacity.as_usize())?;
1126-
Some(ArenaHeap::from(storage))
1127-
}
1128-
1129-
/// Constructs a [`ArenaDeque`] with the given capacity.
1130-
///
1131-
/// # Panics
1132-
/// Panics if the specified capacity cannot be represented by a `usize`, or
1133-
/// if the remaining space in the arena is insufficient. See
1134-
/// [`try_deque`](Arena::try_deque) for a checked version.
1135-
#[track_caller]
1136-
pub fn deque<T, I: Capacity>(&mut self, capacity: I) -> ArenaDeque<'src, T, I> {
1137-
self.try_deque(capacity)
1138-
.expect("unexpected allocation failure in `deque`")
1139-
}
1140-
1141-
/// Constructs a new [`ArenaDeque`] with the given capacity.
1142-
///
1143-
/// Returns [`None`] if the remaining space in the arena is insufficient.
1144-
///
1145-
/// # Panics
1146-
/// Panics if the specified capacity cannot be represented by a `usize`.
1147-
///
1148-
/// # Examples
1149-
/// ```
1150-
/// use coca::Arena;
1151-
/// use core::mem::MaybeUninit;
1152-
///
1153-
/// # fn test() -> Option<()> {
1154-
/// let mut backing_region = [MaybeUninit::uninit(); 1024];
1155-
/// let mut arena = Arena::from(&mut backing_region[..]);
1156-
///
1157-
/// let mut deque = arena.try_deque::<i64, usize>(100)?;
1158-
/// assert!(arena.try_deque::<i64, usize>(100).is_none());
1159-
///
1160-
/// assert_eq!(deque.len(), 0);
1161-
/// assert_eq!(deque.capacity(), 100);
1162-
///
1163-
/// for x in 1..=100 { deque.push_back(x) }
1164-
/// for x in 1..=100 {
1165-
/// assert_eq!(deque.pop_front(), Some(x));
1166-
/// }
1167-
/// # Some(())
1168-
/// # }
1169-
/// # assert!(test().is_some());
1170-
/// ```
1171-
pub fn try_deque<T, I: Capacity>(&mut self, capacity: I) -> Option<ArenaDeque<'src, T, I>> {
1172-
let storage = self.try_storage_with_capacity(capacity.as_usize())?;
1173-
Some(ArenaDeque::from(storage))
1174-
}
1175-
1176-
/// Constructs a new [`DirectArenaPool`] with the specified capacity.
1177-
///
1178-
/// # Panics
1179-
/// Panics if the remaining space in the arena is insufficient. See
1180-
/// [`try_direct_pool`](Arena::try_direct_pool) for a checked version.
1181-
#[track_caller]
1182-
pub fn direct_pool<T, H: Handle>(&mut self, capacity: usize) -> DirectArenaPool<'src, T, H> {
1183-
self.try_direct_pool(capacity)
1184-
.expect("unexpected allocation failure in direct_pool")
1185-
}
1186-
1187-
/// Constructs a new [`DirectArenaPool`] with the specified capacity.
1188-
///
1189-
/// Returns [`None`] if the remaining space in the arena is insufficient.
1190-
///
1191-
/// # Examples
1192-
/// ```
1193-
/// use coca::{Arena, pool::DefaultHandle};
1194-
/// use core::mem::MaybeUninit;
1195-
///
1196-
/// # fn test() -> Option<()> {
1197-
/// let mut backing_region = [MaybeUninit::uninit(); 1024];
1198-
/// let mut arena = Arena::from(&mut backing_region[..]);
1199-
/// let mut pool = arena.try_direct_pool::<&'static str, DefaultHandle>(20)?;
1200-
///
1201-
/// let hello = pool.insert("Hello, World!");
1202-
/// assert_eq!(pool.remove(hello), Some("Hello, World!"));
1203-
/// # Some(())
1204-
/// # }
1205-
/// # assert!(test().is_some());
1206-
/// ```
1207-
pub fn try_direct_pool<T, H: Handle>(
1208-
&mut self,
1209-
capacity: usize,
1210-
) -> Option<DirectArenaPool<'src, T, H>> {
1211-
let storage = self.try_storage_with_capacity(capacity)?;
1212-
Some(DirectArenaPool::from(storage))
1213-
}
1214-
1215-
/// Constructs a new [`PackedArenaPool`] with the specified capacity.
1216-
///
1217-
/// # Panics
1218-
/// Panics if the remaining space in the arena is insufficient. See
1219-
/// [`try_packed_pool`](Arena::try_packed_pool) for a checked version.
1220-
#[track_caller]
1221-
pub fn packed_pool<T, H: Handle>(&mut self, capacity: usize) -> PackedArenaPool<'src, T, H> {
1222-
self.try_packed_pool(capacity)
1223-
.expect("unexpected allocation failure in packed_pool")
1224-
}
1225-
1226-
/// Constructs a new [`PackedArenaPool`] with the specified capacity.
1227-
///
1228-
/// Returns [`None`] if the remaining space in the arena is insufficient.
1229-
///
1230-
/// # Examples
1231-
/// ```
1232-
/// use coca::{Arena, pool::DefaultHandle};
1233-
/// use core::mem::MaybeUninit;
1234-
///
1235-
/// # fn test() -> Option<()> {
1236-
/// let mut backing_region = [MaybeUninit::uninit(); 1024];
1237-
/// let mut arena = Arena::from(&mut backing_region[..]);
1238-
/// let mut pool = arena.try_packed_pool::<&'static str, DefaultHandle>(20)?;
1239-
///
1240-
/// let hello = pool.insert("Hello, World!");
1241-
/// assert_eq!(pool.remove(hello), Some("Hello, World!"));
1242-
/// # Some(())
1243-
/// # }
1244-
/// # assert!(test().is_some());
1245-
/// ```
1246-
pub fn try_packed_pool<T, H: Handle>(&mut self, capacity: usize) -> Option<PackedArenaPool<'src, T, H>> {
1247-
let storage = self.try_storage_with_capacity(capacity)?;
1248-
Some(PackedArenaPool::from(storage))
1249-
}
1250-
1251-
/// Constructs a new [`CacheTable`] with a [`BuildHasherDefault`] and the specified capacity, rounded up to the next multiple of `L::CAPACITY`.
1252-
///
1253-
/// Returns `None` if the remaining space in the arena is insufficient.
1254-
#[allow(clippy::type_complexity)]
1255-
pub fn try_cache<K: Eq + Hash, V, L: crate::cache::CacheLine<K, V>, H: core::hash::Hasher + Default>(&mut self, capacity: usize) -> Option<CacheTable<K, V, ArenaStorage<'src, ArrayLike<L>>, L, BuildHasherDefault<H>>> {
1256-
let capacity = (capacity + L::CAPACITY - 1) / L::CAPACITY;
1257-
let storage = self.try_storage_with_capacity(capacity)?;
1258-
Some(CacheTable::from(storage))
1259-
}
1260-
12611034
/// Constructs a new [`CacheTable`] with the specified hash builder and capacity, rounded up to the next multiple of `L::CAPACITY`.
12621035
///
12631036
/// Returns `None` if the remaining space in the arena is insufficient.
@@ -1268,17 +1041,6 @@ impl<'src> Arena<'src> {
12681041
Some(CacheTable::from_storage_and_hasher(storage, hash_builder))
12691042
}
12701043

1271-
/// Constructs a new [`CacheTable`] with a [`BuildHasherDefault`] and the specified capacity, rounded up to the next multiple of `L::CAPACITY`.
1272-
///
1273-
/// # Panics
1274-
/// Panics if the remaining space in the arena is insufficient to exhaust
1275-
/// the iterator. See [`try_cache`](Arena::try_cache) for a checked
1276-
/// version that never panics.
1277-
pub fn cache<K: Eq + Hash, V, L: crate::cache::CacheLine<K, V>, H: core::hash::Hasher + Default>(&mut self, capacity: usize) -> CacheTable<K, V, ArenaStorage<'src, ArrayLike<L>>, L, BuildHasherDefault<H>> {
1278-
self.try_cache(capacity)
1279-
.expect("unexpected allocation failure in cache")
1280-
}
1281-
12821044
/// Constructs a new [`CacheTable`] with the specified hash builder and capacity, rounded up to the next multiple of `L::CAPACITY`.
12831045
///
12841046
/// # Panics

0 commit comments

Comments
 (0)