implicit_predicates_core/scratch/growable.rs
1//! The arena that owns its memory and grows on the heap.
2
3use alloc::vec;
4
5use super::Scratch;
6use super::span::to_index;
7use super::storage::{Storage, clamp_capacity};
8
9impl Scratch<'static> {
10 /// Creates an empty arena that owns its memory, with room for `initial`
11 /// components (at most `u32::MAX`, the most an arena uses).
12 ///
13 /// When an operation needs more room the arena grows on the heap to at
14 /// least double its capacity, or to what the operation needs if that is
15 /// more, keeping its contents. Spans are indices, so they stay valid
16 /// after the buffer moves. The arena fails with
17 /// [`ScratchExhausted`](super::ScratchExhausted) only when an operation
18 /// needs more than `u32::MAX` components, and then it is unchanged.
19 ///
20 /// Running out of memory aborts, as for any `alloc` collection;
21 /// `ScratchExhausted` is returned only when the arena would exceed
22 /// `u32::MAX` components.
23 ///
24 /// Available only with the `alloc` cargo feature.
25 ///
26 /// # Examples
27 ///
28 /// ```
29 /// use implicit_predicates_core::Scratch;
30 ///
31 /// let mut scratch = Scratch::growable(1);
32 /// let a = scratch.push(&[1e-20, 1.0])?; // grows
33 /// assert!(scratch.capacity() >= 2);
34 /// assert_eq!(scratch.get(a), &[1e-20, 1.0]);
35 /// # Ok::<(), implicit_predicates_core::ScratchExhausted>(())
36 /// ```
37 #[must_use]
38 pub fn growable(initial: usize) -> Scratch<'static> {
39 // Components past `u32::MAX` could never be used, so never allocate them.
40 let initial = to_index(clamp_capacity(initial));
41 Scratch {
42 storage: Storage::Owned(vec![0.0; initial]),
43 used: 0,
44 high_water: 0,
45 }
46 }
47}