bump_scope/
bump_scope_guard.rs1use core::{fmt::Debug, num::NonZeroUsize, ptr::NonNull};
2
3use crate::{
4 BumpScope,
5 alloc::Allocator,
6 chunk::ChunkHeader,
7 polyfill::transmute_mut,
8 raw_bump::{RawBump, RawChunk},
9 settings::{BumpAllocatorSettings, BumpSettings},
10 stats::AnyStats,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct Checkpoint {
19 pub(crate) chunk: NonNull<ChunkHeader>,
20 pub(crate) address: NonZeroUsize,
21}
22
23impl Checkpoint {
24 pub(crate) fn new<S: BumpAllocatorSettings>(chunk: RawChunk<S>) -> Self {
25 let address = chunk.pos().addr();
26 let chunk = chunk.header.cast();
27 Checkpoint { chunk, address }
28 }
29
30 pub(crate) unsafe fn reset_within_chunk(self) {
31 unsafe {
32 let ptr = self.chunk.cast::<u8>().with_addr(self.address);
33 self.chunk.as_ref().pos.set(ptr);
34 }
35 }
36}
37
38#[must_use]
42pub struct BumpScopeGuard<'a, A, S = BumpSettings>
43where
44 A: Allocator,
45 S: BumpAllocatorSettings,
46{
47 bump: &'a mut RawBump<A, S>,
48 checkpoint: Checkpoint,
49}
50
51impl<A, S> Debug for BumpScopeGuard<'_, A, S>
52where
53 A: Allocator,
54 S: BumpAllocatorSettings,
55{
56 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57 AnyStats::from(self.bump.stats()).debug_format("BumpScopeGuard", f)
58 }
59}
60
61impl<A, S> Drop for BumpScopeGuard<'_, A, S>
62where
63 A: Allocator,
64 S: BumpAllocatorSettings,
65{
66 #[inline(always)]
67 fn drop(&mut self) {
68 self.reset();
69 }
70}
71
72impl<'a, A, S> BumpScopeGuard<'a, A, S>
73where
74 A: Allocator,
75 S: BumpAllocatorSettings,
76{
77 #[inline(always)]
78 pub(crate) fn new(bump: &'a mut RawBump<A, S>) -> Self {
79 let checkpoint = bump.checkpoint();
80 Self { bump, checkpoint }
81 }
82
83 #[inline(always)]
85 pub fn scope(&mut self) -> &mut BumpScope<'_, A, S> {
86 unsafe { transmute_mut(self.bump) }
87 }
88
89 #[inline(always)]
91 pub fn reset(&mut self) {
92 unsafe { self.bump.reset_to(self.checkpoint) }
93 }
94}