fallacy_box/lib.rs
1//! A pointer type for heap allocation.
2
3#![feature(allocator_api)]
4
5pub use fallacy_clone::{AllocError, TryClone};
6pub use std::alloc::{Allocator, Global, Layout};
7
8use std::boxed::Box as StdBox;
9use std::fmt;
10use std::hash::Hash;
11use std::ops::{Deref, DerefMut};
12use std::result::Result;
13
14/// A pointer type for heap allocation.
15#[derive(Ord, PartialOrd, Eq, PartialEq, Hash)]
16#[repr(transparent)]
17pub struct Box<T: ?Sized, A: Allocator = Global>(StdBox<T, A>);
18
19impl<T> Box<T> {
20 /// Allocates memory on the heap then places `x` into it,
21 /// returning an error if the allocation fails
22 ///
23 /// This doesn't actually allocate if `T` is zero-sized.
24 #[inline]
25 pub fn try_new(x: T) -> Result<Self, AllocError> {
26 Ok(Box(StdBox::try_new(x).map_err(|_| AllocError::new(Layout::new::<T>()))?))
27 }
28}
29
30impl<T: ?Sized> Box<T> {
31 /// Constructs a box from a raw pointer.
32 ///
33 /// After calling this function, the raw pointer is owned by the
34 /// resulting `Box`. Specifically, the `Box` destructor will call
35 /// the destructor of `T` and free the allocated memory. For this
36 /// to be safe, the memory must have been allocated in accordance
37 /// with the [memory layout] used by `Box` .
38 ///
39 /// # Safety
40 ///
41 /// This function is unsafe because improper use may lead to
42 /// memory problems. For example, a double-free may occur if the
43 /// function is called twice on the same raw pointer.
44 #[inline]
45 pub unsafe fn from_raw(raw: *mut T) -> Self {
46 Box(StdBox::from_raw(raw))
47 }
48}
49
50impl<T, A: Allocator> Box<T, A> {
51 /// Allocates memory in the given allocator then places `x` into it,
52 /// returning an error if the allocation fails
53 ///
54 /// This doesn't actually allocate if `T` is zero-sized.
55 #[inline]
56 pub fn try_new_in(x: T, alloc: A) -> Result<Self, AllocError> {
57 Ok(Box(
58 StdBox::try_new_in(x, alloc).map_err(|_| AllocError::new(Layout::new::<T>()))?
59 ))
60 }
61}
62
63impl<T: ?Sized, A: Allocator> Box<T, A> {
64 /// Constructs a box from a raw pointer in the given allocator.
65 ///
66 /// After calling this function, the raw pointer is owned by the
67 /// resulting `Box`. Specifically, the `Box` destructor will call
68 /// the destructor of `T` and free the allocated memory. For this
69 /// to be safe, the memory must have been allocated in accordance
70 /// with the [memory layout] used by `Box` .
71 ///
72 /// # Safety
73 ///
74 /// This function is unsafe because improper use may lead to
75 /// memory problems. For example, a double-free may occur if the
76 /// function is called twice on the same raw pointer.
77 #[inline]
78 pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
79 Box(StdBox::from_raw_in(raw, alloc))
80 }
81
82 /// Consumes the `Box`, returning a wrapped raw pointer.
83 ///
84 /// The pointer will be properly aligned and non-null.
85 ///
86 /// After calling this function, the caller is responsible for the
87 /// memory previously managed by the `Box`. In particular, the
88 /// caller should properly destroy `T` and release the memory, taking
89 /// into account the [memory layout] used by `Box`. The easiest way to
90 /// do this is to convert the raw pointer back into a `Box` with the
91 /// [`Box::from_raw`] function, allowing the `Box` destructor to perform
92 /// the cleanup.
93 ///
94 /// Note: this is an associated function, which means that you have
95 /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This
96 /// is so that there is no conflict with a method on the inner type.
97 #[inline]
98 pub fn into_raw(b: Self) -> *mut T {
99 StdBox::into_raw(b.0)
100 }
101
102 /// Consumes the `Box`, returning a wrapped raw pointer and the allocator.
103 ///
104 /// The pointer will be properly aligned and non-null.
105 ///
106 /// After calling this function, the caller is responsible for the
107 /// memory previously managed by the `Box`. In particular, the
108 /// caller should properly destroy `T` and release the memory, taking
109 /// into account the [memory layout] used by `Box`. The easiest way to
110 /// do this is to convert the raw pointer back into a `Box` with the
111 /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform
112 /// the cleanup.
113 ///
114 /// Note: this is an associated function, which means that you have
115 /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This
116 /// is so that there is no conflict with a method on the inner type.
117 #[inline]
118 pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
119 StdBox::into_raw_with_allocator(b.0)
120 }
121
122 /// Returns a reference to the underlying allocator.
123 ///
124 /// Note: this is an associated function, which means that you have
125 /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This
126 /// is so that there is no conflict with a method on the inner type.
127 #[inline]
128 pub fn allocator(b: &Self) -> &A {
129 StdBox::allocator(&b.0)
130 }
131
132 /// Consumes and leaks the `Box`, returning a mutable reference,
133 /// `&'a mut T`. Note that the type `T` must outlive the chosen lifetime
134 /// `'a`. If the type has only static references, or none at all, then this
135 /// may be chosen to be `'static`.
136 ///
137 /// This function is mainly useful for data that lives for the remainder of
138 /// the program's life. Dropping the returned reference will cause a memory
139 /// leak. If this is not acceptable, the reference should first be wrapped
140 /// with the [`Box::from_raw`] function producing a `Box`. This `Box` can
141 /// then be dropped which will properly destroy `T` and release the
142 /// allocated memory.
143 ///
144 /// Note: this is an associated function, which means that you have
145 /// to call it as `Box::leak(b)` instead of `b.leak()`. This
146 /// is so that there is no conflict with a method on the inner type.
147 #[inline]
148 pub fn leak<'a>(b: Self) -> &'a mut T
149 where
150 A: 'a,
151 {
152 StdBox::leak(b.0)
153 }
154
155 #[inline]
156 pub fn into_std(self) -> StdBox<T, A> {
157 self.0
158 }
159
160 #[inline]
161 pub fn from_std(b: StdBox<T, A>) -> Self {
162 Box(b)
163 }
164}
165
166impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
167 type Target = T;
168
169 #[inline]
170 fn deref(&self) -> &T {
171 self.0.deref()
172 }
173}
174
175impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
176 #[inline]
177 fn deref_mut(&mut self) -> &mut T {
178 self.0.deref_mut()
179 }
180}
181
182impl<T: ?Sized, A: Allocator> AsRef<T> for Box<T, A> {
183 #[inline]
184 fn as_ref(&self) -> &T {
185 self.0.as_ref()
186 }
187}
188
189impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
190 #[inline]
191 fn as_mut(&mut self) -> &mut T {
192 self.0.as_mut()
193 }
194}
195
196impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for Box<T, A> {
197 #[inline]
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 fmt::Display::fmt(&self.0, f)
200 }
201}
202
203impl<T: fmt::Debug + ?Sized, A: Allocator> fmt::Debug for Box<T, A> {
204 #[inline]
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 fmt::Debug::fmt(&self.0, f)
207 }
208}
209
210impl<T: ?Sized, A: Allocator> fmt::Pointer for Box<T, A> {
211 #[inline]
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 fmt::Pointer::fmt(&self.0, f)
214 }
215}
216
217impl<T: TryClone, A: Allocator + TryClone> TryClone for Box<T, A> {
218 #[inline]
219 fn try_clone(&self) -> Result<Self, AllocError> {
220 let clone = self.0.try_clone()?;
221 Ok(Box::from_std(clone))
222 }
223
224 #[inline]
225 fn try_clone_from(&mut self, source: &Self) -> Result<(), AllocError> {
226 self.as_mut().try_clone_from(source)
227 }
228}
229
230#[cfg(feature = "serde")]
231mod serde {
232 use crate::Box;
233 use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
234
235 impl<T> Serialize for Box<T>
236 where
237 T: ?Sized + Serialize,
238 {
239 #[inline]
240 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
241 where
242 S: Serializer,
243 {
244 (**self).serialize(serializer)
245 }
246 }
247
248 impl<'de, T> Deserialize<'de> for Box<T>
249 where
250 T: Deserialize<'de>,
251 {
252 #[inline]
253 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
254 where
255 D: Deserializer<'de>,
256 {
257 let val = Deserialize::deserialize(deserializer)?;
258 Box::try_new(val).map_err(D::Error::custom)
259 }
260 }
261}