1use std::ops::Deref;
5
6#[cfg(debug_assertions)]
7use super::debug;
8use super::{Arena, release};
9use crate::apperr;
10use crate::helpers::*;
11
12static mut S_SCRATCH: [release::Arena; 2] =
13 const { [release::Arena::empty(), release::Arena::empty()] };
14
15pub fn init(capacity: usize) -> apperr::Result<()> {
18 unsafe {
19 for s in &mut S_SCRATCH[..] {
20 *s = release::Arena::new(capacity)?;
21 }
22 }
23 Ok(())
24}
25
26pub fn scratch_arena(conflict: Option<&Arena>) -> ScratchArena<'static> {
48 unsafe {
49 #[cfg(debug_assertions)]
50 let conflict = conflict.map(|a| a.delegate_target_unchecked());
51
52 let index = opt_ptr_eq(conflict, Some(&S_SCRATCH[0])) as usize;
53 let arena = &S_SCRATCH[index];
54 ScratchArena::new(arena)
55 }
56}
57
58#[cfg(debug_assertions)]
62pub struct ScratchArena<'a> {
63 arena: debug::Arena,
64 offset: usize,
65 _phantom: std::marker::PhantomData<&'a ()>,
66}
67
68#[cfg(not(debug_assertions))]
69pub struct ScratchArena<'a> {
70 arena: &'a Arena,
71 offset: usize,
72}
73
74#[cfg(debug_assertions)]
75impl<'a> ScratchArena<'a> {
76 fn new(arena: &'a release::Arena) -> Self {
77 let offset = arena.offset();
78 ScratchArena { arena: Arena::delegated(arena), _phantom: std::marker::PhantomData, offset }
79 }
80}
81
82#[cfg(not(debug_assertions))]
83impl<'a> ScratchArena<'a> {
84 fn new(arena: &'a release::Arena) -> Self {
85 let offset = arena.offset();
86 ScratchArena { arena, offset }
87 }
88}
89
90impl Drop for ScratchArena<'_> {
91 fn drop(&mut self) {
92 unsafe { self.arena.reset(self.offset) };
93 }
94}
95
96#[cfg(debug_assertions)]
97impl Deref for ScratchArena<'_> {
98 type Target = debug::Arena;
99
100 fn deref(&self) -> &Self::Target {
101 &self.arena
102 }
103}
104
105#[cfg(not(debug_assertions))]
106impl Deref for ScratchArena<'_> {
107 type Target = Arena;
108
109 fn deref(&self) -> &Self::Target {
110 self.arena
111 }
112}