1use super::{AllocErr, UninitAlloc};
2use std::{
3 alloc::{dealloc, Layout},
4 fmt,
5 marker::PhantomData,
6 mem,
7 ops::{Deref, DerefMut},
8 ptr::NonNull,
9};
10
11pub struct OwnedAlloc<T>
17where
18 T: ?Sized,
19{
20 nnptr: NonNull<T>,
21 _marker: PhantomData<T>,
22}
23
24impl<T> OwnedAlloc<T> {
25 pub fn new(val: T) -> Self {
28 UninitAlloc::new().init(val)
29 }
30
31 pub fn try_new(val: T) -> Result<Self, AllocErr> {
34 UninitAlloc::try_new().map(|alloc| alloc.init(val))
35 }
36
37 pub fn move_inner(self) -> (T, UninitAlloc<T>) {
40 let val = unsafe { self.nnptr.as_ptr().read() };
41 let alloc = unsafe { UninitAlloc::from_raw(self.nnptr) };
42 mem::forget(self);
43 (val, alloc)
44 }
45}
46
47impl<T> OwnedAlloc<T>
48where
49 T: ?Sized,
50{
51 pub unsafe fn from_raw(nnptr: NonNull<T>) -> Self {
58 Self { nnptr, _marker: PhantomData }
59 }
60
61 pub unsafe fn from_box(boxed: Box<T>) -> Self {
68 Self::from_raw(NonNull::new_unchecked(Box::into_raw(boxed)))
69 }
70
71 pub fn raw(&self) -> NonNull<T> {
73 self.nnptr
74 }
75
76 pub fn into_raw(self) -> NonNull<T> {
79 let nnptr = self.nnptr;
80 mem::forget(self);
81 nnptr
82 }
83
84 pub unsafe fn into_box(self) -> Box<T> {
91 Box::from_raw(self.into_raw().as_ptr())
92 }
93
94 pub fn drop_in_place(self) -> UninitAlloc<T> {
97 unsafe {
98 self.nnptr.as_ptr().drop_in_place();
99 UninitAlloc::from_raw(self.into_raw())
100 }
101 }
102
103 pub fn forget_inner(self) -> UninitAlloc<T> {
106 unsafe { UninitAlloc::from_raw(self.into_raw()) }
107 }
108}
109
110impl<T> Drop for OwnedAlloc<T>
111where
112 T: ?Sized,
113{
114 fn drop(&mut self) {
115 unsafe {
116 let layout = Layout::for_value(self.nnptr.as_ref());
117 self.nnptr.as_ptr().drop_in_place();
118 if layout.size() != 0 {
119 dealloc(self.nnptr.cast().as_ptr(), layout);
120 }
121 }
122 }
123}
124
125impl<T> Deref for OwnedAlloc<T>
126where
127 T: ?Sized,
128{
129 type Target = T;
130
131 fn deref(&self) -> &T {
132 unsafe { self.nnptr.as_ref() }
133 }
134}
135
136impl<T> DerefMut for OwnedAlloc<T>
137where
138 T: ?Sized,
139{
140 fn deref_mut(&mut self) -> &mut T {
141 unsafe { self.nnptr.as_mut() }
142 }
143}
144
145impl<T> fmt::Debug for OwnedAlloc<T>
146where
147 T: ?Sized,
148{
149 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
150 write!(fmtr, "{:?}", self.nnptr)
151 }
152}
153
154impl<T> Clone for OwnedAlloc<T>
155where
156 T: Clone,
157{
158 fn clone(&self) -> Self {
159 Self::new((**self).clone())
160 }
161}
162
163impl<T> From<T> for OwnedAlloc<T> {
164 fn from(val: T) -> Self {
165 Self::new(val)
166 }
167}
168
169unsafe impl<T> Send for OwnedAlloc<T> where T: ?Sized + Send {}
170unsafe impl<T> Sync for OwnedAlloc<T> where T: ?Sized + Sync {}
171
172#[cfg(test)]
173mod test {
174 use super::OwnedAlloc;
175
176 #[test]
177 fn inner_eq() {
178 let mut alloc = OwnedAlloc::new(20);
179
180 assert_eq!(*alloc, 20);
181
182 *alloc = 30;
183
184 assert_eq!(*alloc, 30);
185 }
186
187 #[test]
188 fn move_inner_eq() {
189 let alloc = OwnedAlloc::new(20);
190
191 assert_eq!(alloc.move_inner().0, 20);
192 }
193
194 #[test]
195 fn from_into_std_box() {
196 let boxed = unsafe { OwnedAlloc::new([5u128; 32]).into_box() };
197 assert_eq!(*boxed, [5; 32]);
198 let raw = unsafe { OwnedAlloc::from_box(boxed) };
199 assert_eq!(*raw, [5; 32]);
200 }
201}