base/pointer/
unique.rs

1/// An allocator-aware smart pointer similar to C++'s `unique_ptr`.
2///
3/// # Usage
4///
5/// ```no_compile
6/// let pointer = Unique::new(100_000);
7/// let num = *pointer;
8/// ```
9///
10/// TODO: Write better documentation.
11pub struct Unique<T: ?Sized, A: Allocator = GlobalAllocator> {
12   pointer: NonNull<T>,
13   allocator: A,
14   _ghost: PhantomData<T>,
15}
16
17impl<T, A: Allocator> Unique<T, A> {
18   pub fn new_with(value: T, mut allocator: A) -> Self {
19      let mut pointer =
20         unsafe {
21            allocate::<T>(&mut allocator)
22               .expect("allocation failure")
23               .cast::<T>()
24         };
25
26      unsafe {
27         write::<T>(pointer.as_mut(), value);
28      }
29
30      return Unique {
31         pointer,
32         allocator,
33         _ghost: PhantomData,
34      };
35   }
36
37   pub fn pin_with(value: T, allocator: A) -> Pin<Self> {
38      return unsafe { Pin::new_unchecked(Self::new_with(value, allocator)) };
39   }
40}
41
42impl<T: ?Sized, A: Allocator> Unique<T, A> {
43   pub unsafe fn from_raw_with(pointer: NonNull<T>, allocator: A) -> Self {
44      return Unique {
45         pointer,
46         allocator,
47         _ghost: PhantomData,
48      };
49   }
50
51   pub fn leak<'a>(unique: Unique<T, A>) -> &'a mut T
52   where
53      A: 'a, {
54      let reference = unsafe { &mut *unique.pointer.as_ptr() };
55      core::mem::forget(unique);
56
57      return reference;
58   }
59
60   pub fn into_raw(unique: Self) -> *mut T {
61      let pointer = unique.pointer.as_ptr();
62      core::mem::forget(unique);
63
64      return pointer;
65   }
66}
67
68impl<T> Unique<T, GlobalAllocator> {
69   pub fn new(value: T) -> Self {
70      return Unique::new_with(value, GlobalAllocator);
71   }
72
73   pub fn pin(value: T) -> Pin<Self> {
74      return Self::pin_with(value, GlobalAllocator);
75   }
76}
77
78impl<T: ?Sized, A: Allocator> Deref for Unique<T, A> {
79   type Target = T;
80
81   #[inline]
82   fn deref(&self) -> &Self::Target {
83      return unsafe { self.pointer.as_ref() };
84   }
85}
86
87impl<T: ?Sized, A: Allocator> DerefMut for Unique<T, A> {
88   fn deref_mut(&mut self) -> &mut Self::Target {
89      return unsafe { self.pointer.as_mut() };
90   }
91}
92
93impl<T: ?Sized, A: Allocator> AsRef<T> for Unique<T, A> {
94   #[inline]
95   fn as_ref(&self) -> &T {
96      return self;
97   }
98}
99
100impl<T: ?Sized, A: Allocator> AsMut<T> for Unique<T, A> {
101   #[inline]
102   fn as_mut(&mut self) -> &mut T {
103      return self;
104   }
105}
106
107impl<T: ?Sized, A: Allocator> Borrow<T> for Unique<T, A> {
108   #[inline]
109   fn borrow(&self) -> &T {
110      return self;
111   }
112}
113
114impl<T: ?Sized, A: Allocator> BorrowMut<T> for Unique<T, A> {
115   #[inline]
116   fn borrow_mut(&mut self) -> &mut T {
117      return self;
118   }
119}
120
121impl<T: ?Sized, A: Allocator> Drop for Unique<T, A> {
122   fn drop(&mut self) {
123      let size = unsafe { size_of_val(self.pointer.as_ref()) };
124      let layout = Layout::from_size(size);
125
126      unsafe {
127         drop_in_place(self.pointer.as_ptr());
128         self
129            .allocator
130            .deallocate(self.pointer.cast().as_ptr(), layout);
131      }
132   }
133}
134
135impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Unique<U, A>> for Unique<T, A> {}
136
137impl<T: ?Sized, A: Allocator> Unpin for Unique<T, A> {}
138
139// IMPORTS //
140
141use {
142   crate::alloc::{allocate, Allocator, GlobalAllocator, Layout},
143   core::{
144      borrow::{Borrow, BorrowMut},
145      convert::{AsMut, AsRef},
146      marker::{PhantomData, Unsize},
147      mem::size_of_val,
148      ops::{CoerceUnsized, Deref, DerefMut},
149      pin::Pin,
150      ptr::{drop_in_place, write, NonNull},
151   },
152};