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}