Skip to main content

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}