Skip to main content

bumparaw_collections/
alloc.rs

1use std::{
2    borrow::Borrow,
3    cell::Ref,
4    ops::{Deref, DerefMut},
5};
6
7use allocator_api2::alloc::Allocator;
8use bumpalo::Bump;
9
10/// A newtype wrapper to implement [`Allocator`] on `Ref<Bump>`.
11pub struct RefBump<'bump>(Ref<'bump, Bump>);
12
13impl<'bump> RefBump<'bump> {
14    /// Wraps a `Ref<Bump>` into a type that implements the [`Allocator`] trait.
15    pub fn new(r: Ref<'bump, Bump>) -> Self {
16        Self(r)
17    }
18
19    /// Clones the wrapped `Ref<Bump>`.
20    ///
21    /// See [`Ref::clone`] for more information.
22    #[allow(clippy::should_implement_trait)] // really, go see [`Ref::clone`]
23    pub fn clone(orig: &RefBump<'bump>) -> RefBump<'bump> {
24        Self(Ref::clone(&orig.0))
25    }
26
27    /// Makes a new [`Ref`] for a component of the borrowed data.
28    ///
29    /// See [`Ref::map`] for more information.
30    pub fn map<T, F>(orig: RefBump<'bump>, f: F) -> Ref<'bump, T>
31    where
32        F: FnOnce(&Bump) -> &T,
33        T: ?Sized,
34    {
35        Ref::map(orig.0, f)
36    }
37
38    /// Makes a new [`Ref`] for an optional component of the borrowed data.
39    /// The original guard is returned as an `Err(..)` if the closure returns None.
40    ///
41    /// See [`Ref::filter_map`] for more information.
42    pub fn filter_map<T, F>(orig: RefBump<'bump>, f: F) -> Result<Ref<'bump, T>, RefBump<'bump>>
43    where
44        F: FnOnce(&Bump) -> Option<&T>,
45        T: ?Sized,
46    {
47        Ref::filter_map(orig.0, f).map_err(RefBump)
48    }
49
50    /// Splits a Ref into multiple Refs for different components of the borrowed data.
51    ///
52    /// See [`Ref::filter_map`] for more information.
53    pub fn map_split<T, U, F>(orig: RefBump<'bump>, f: F) -> (Ref<'bump, T>, Ref<'bump, U>)
54    where
55        F: FnOnce(&Bump) -> (&T, &U),
56        T: ?Sized,
57        U: ?Sized,
58    {
59        Ref::map_split(orig.0, f)
60    }
61}
62
63impl<'bump> Deref for RefBump<'bump> {
64    type Target = Ref<'bump, Bump>;
65
66    fn deref(&self) -> &Self::Target {
67        &self.0
68    }
69}
70
71impl DerefMut for RefBump<'_> {
72    fn deref_mut(&mut self) -> &mut Self::Target {
73        &mut self.0
74    }
75}
76
77unsafe impl Allocator for RefBump<'_> {
78    #[inline]
79    fn allocate(
80        &self,
81        layout: std::alloc::Layout,
82    ) -> Result<std::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
83        self.0.deref().allocate(layout)
84    }
85
86    #[inline]
87    unsafe fn deallocate(&self, ptr: std::ptr::NonNull<u8>, layout: std::alloc::Layout) {
88        self.0.deref().deallocate(ptr, layout)
89    }
90
91    #[inline]
92    fn allocate_zeroed(
93        &self,
94        layout: std::alloc::Layout,
95    ) -> Result<std::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
96        self.0.deref().allocate_zeroed(layout)
97    }
98
99    #[inline]
100    unsafe fn grow(
101        &self,
102        ptr: std::ptr::NonNull<u8>,
103        old_layout: std::alloc::Layout,
104        new_layout: std::alloc::Layout,
105    ) -> Result<std::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
106        self.0.deref().grow(ptr, old_layout, new_layout)
107    }
108
109    #[inline]
110    unsafe fn grow_zeroed(
111        &self,
112        ptr: std::ptr::NonNull<u8>,
113        old_layout: std::alloc::Layout,
114        new_layout: std::alloc::Layout,
115    ) -> Result<std::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
116        self.0.deref().grow_zeroed(ptr, old_layout, new_layout)
117    }
118
119    #[inline]
120    unsafe fn shrink(
121        &self,
122        ptr: std::ptr::NonNull<u8>,
123        old_layout: std::alloc::Layout,
124        new_layout: std::alloc::Layout,
125    ) -> Result<std::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
126        self.0.deref().shrink(ptr, old_layout, new_layout)
127    }
128
129    #[inline]
130    fn by_ref(&self) -> &Self
131    where
132        Self: Sized,
133    {
134        self
135    }
136}
137
138/// A newtype wrapper to implement common traits of `str` on `Ref<str>`.
139#[derive(Debug)]
140pub struct RefStr<'bump>(pub Ref<'bump, str>);
141
142impl std::hash::Hash for RefStr<'_> {
143    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
144        self.0.hash(state);
145    }
146}
147
148impl PartialEq for RefStr<'_> {
149    fn eq(&self, other: &Self) -> bool {
150        self.0.deref() == other.0.deref()
151    }
152}
153
154impl Eq for RefStr<'_> {}
155
156impl Borrow<str> for RefStr<'_> {
157    fn borrow(&self) -> &str {
158        self
159    }
160}
161
162impl Deref for RefStr<'_> {
163    type Target = str;
164
165    fn deref(&self) -> &Self::Target {
166        &self.0
167    }
168}
169
170impl AsRef<str> for RefStr<'_> {
171    fn as_ref(&self) -> &str {
172        self
173    }
174}
175
176/// A newtype wrapper to implement common traits of `[u8]` on `Ref<[u8]>`.
177#[derive(Debug)]
178pub struct RefBytes<'bump>(pub Ref<'bump, [u8]>);
179
180impl std::hash::Hash for RefBytes<'_> {
181    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
182        self.0.hash(state);
183    }
184}
185
186impl PartialEq for RefBytes<'_> {
187    fn eq(&self, other: &Self) -> bool {
188        self.0.deref() == other.0.deref()
189    }
190}
191
192impl Eq for RefBytes<'_> {}
193
194impl Borrow<[u8]> for RefBytes<'_> {
195    fn borrow(&self) -> &[u8] {
196        self
197    }
198}
199
200impl Deref for RefBytes<'_> {
201    type Target = [u8];
202
203    fn deref(&self) -> &Self::Target {
204        &self.0
205    }
206}
207
208impl AsRef<[u8]> for RefBytes<'_> {
209    fn as_ref(&self) -> &[u8] {
210        self
211    }
212}