1use core::{fmt::Debug, marker::PhantomData, num::NonZeroUsize, ptr::NonNull};
2
3use crate::{
4 Bump, BumpScope, MinimumAlignment, RawChunk, SupportedMinimumAlignment,
5 alloc::Allocator,
6 chunk_header::ChunkHeader,
7 stats::{AnyStats, Stats},
8};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct Checkpoint {
13 pub(crate) chunk: NonNull<ChunkHeader>,
14 pub(crate) address: NonZeroUsize,
15}
16
17impl Checkpoint {
18 pub(crate) fn new<A, const UP: bool, const GUARANTEED_ALLOCATED: bool>(
19 chunk: RawChunk<A, UP, GUARANTEED_ALLOCATED>,
20 ) -> Self {
21 let address = chunk.pos().addr();
22 let chunk = chunk.header().cast();
23 Checkpoint { chunk, address }
24 }
25
26 pub(crate) unsafe fn reset_within_chunk(self) {
27 unsafe {
28 let ptr = self.chunk.cast::<u8>().with_addr(self.address);
29 self.chunk.as_ref().pos.set(ptr);
30 }
31 }
32}
33
34pub struct BumpScopeGuard<'a, A, const MIN_ALIGN: usize = 1, const UP: bool = true, const DEALLOCATES: bool = true>
36where
37 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
38{
39 pub(crate) chunk: RawChunk<A, UP, true>,
40 address: usize,
41 marker: PhantomData<&'a mut ()>,
42}
43
44impl<A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool> Debug
45 for BumpScopeGuard<'_, A, MIN_ALIGN, UP, DEALLOCATES>
46where
47 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
48{
49 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50 AnyStats::from(self.stats()).debug_format("BumpScopeGuard", f)
51 }
52}
53
54impl<A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool> Drop
55 for BumpScopeGuard<'_, A, MIN_ALIGN, UP, DEALLOCATES>
56where
57 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
58{
59 #[inline(always)]
60 fn drop(&mut self) {
61 self.reset();
62 }
63}
64
65impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool>
66 BumpScopeGuard<'a, A, MIN_ALIGN, UP, DEALLOCATES>
67where
68 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
69{
70 #[inline(always)]
71 pub(crate) fn new(bump: &'a mut BumpScope<'_, A, MIN_ALIGN, UP, true, DEALLOCATES>) -> Self {
72 unsafe { Self::new_unchecked(bump.chunk.get()) }
73 }
74
75 #[inline(always)]
76 pub(crate) unsafe fn new_unchecked(chunk: RawChunk<A, UP, true>) -> Self {
77 Self {
78 chunk,
79 address: chunk.pos().addr().get(),
80 marker: PhantomData,
81 }
82 }
83
84 #[inline(always)]
86 pub fn scope(&mut self) -> BumpScope<'_, A, MIN_ALIGN, UP, true, DEALLOCATES> {
87 unsafe { BumpScope::new_unchecked(self.chunk) }
88 }
89
90 #[inline(always)]
92 pub fn reset(&mut self) {
93 unsafe {
94 self.chunk.set_pos_addr(self.address);
95 }
96 }
97
98 #[must_use]
100 #[inline(always)]
101 pub fn stats(&self) -> Stats<'a, A, UP> {
102 self.chunk.stats()
103 }
104
105 #[must_use]
107 #[inline(always)]
108 pub fn allocator(&self) -> &'a A {
109 self.stats().current_chunk().allocator()
110 }
111}
112
113pub struct BumpScopeGuardRoot<'b, A, const MIN_ALIGN: usize = 1, const UP: bool = true, const DEALLOCATES: bool = true>
121where
122 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
123 A: Allocator,
124{
125 pub(crate) chunk: RawChunk<A, UP, true>,
126 marker: PhantomData<&'b mut ()>,
127}
128
129impl<A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool> Debug
130 for BumpScopeGuardRoot<'_, A, MIN_ALIGN, UP, DEALLOCATES>
131where
132 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
133 A: Allocator,
134{
135 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
136 AnyStats::from(self.stats()).debug_format("BumpScopeGuardRoot", f)
137 }
138}
139
140impl<A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool> Drop
141 for BumpScopeGuardRoot<'_, A, MIN_ALIGN, UP, DEALLOCATES>
142where
143 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
144 A: Allocator,
145{
146 #[inline(always)]
147 fn drop(&mut self) {
148 self.reset();
149 }
150}
151
152impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool>
153 BumpScopeGuardRoot<'a, A, MIN_ALIGN, UP, DEALLOCATES>
154where
155 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
156 A: Allocator,
157{
158 #[inline(always)]
159 pub(crate) fn new(bump: &'a mut Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>) -> Self {
160 unsafe { Self::new_unchecked(bump.chunk.get()) }
161 }
162
163 #[inline(always)]
164 pub(crate) unsafe fn new_unchecked(chunk: RawChunk<A, UP, true>) -> Self {
165 Self {
166 chunk,
167 marker: PhantomData,
168 }
169 }
170
171 #[inline(always)]
173 pub fn scope(&mut self) -> BumpScope<'_, A, MIN_ALIGN, UP, true, DEALLOCATES> {
174 unsafe { BumpScope::new_unchecked(self.chunk) }
175 }
176
177 #[inline(always)]
179 pub fn reset(&mut self) {
180 self.chunk.reset();
181 }
182
183 #[must_use]
185 #[inline(always)]
186 pub fn stats(&self) -> Stats<'a, A, UP> {
187 self.chunk.stats()
188 }
189
190 #[must_use]
192 #[inline(always)]
193 pub fn allocator(&self) -> &'a A {
194 self.stats().current_chunk().allocator()
195 }
196}