tux_owned_alloc/
uninit.rs1use super::{AllocErr, OwnedAlloc, RawVec};
2use std::{
3 alloc::{alloc, dealloc, handle_alloc_error, Layout},
4 fmt,
5 marker::PhantomData,
6 mem,
7 ptr::NonNull,
8};
9
10pub struct UninitAlloc<T>
16 where
17 T: ?Sized,
18{
19 nnptr: NonNull<T>,
20 _marker: PhantomData<T>,
21}
22
23impl<T> Default for UninitAlloc<T>
24{
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl<T> UninitAlloc<T> {
31 pub fn new() -> Self {
34 Self::try_new().unwrap_or_else(|err| handle_alloc_error(err.layout))
35 }
36
37 pub fn try_new() -> Result<Self, AllocErr> {
39 let layout = Layout::new::<T>();
40
41 let res = if layout.size() == 0 {
42 Ok(NonNull::dangling())
43 } else {
44 NonNull::new(unsafe { alloc(layout) })
45 .map(NonNull::cast::<T>)
46 .ok_or(AllocErr { layout })
47 };
48
49 res.map(|nnptr| Self { nnptr, _marker: PhantomData })
50 }
51
52 pub fn init(self, val: T) -> OwnedAlloc<T> {
55 let raw = self.into_raw();
56 unsafe {
57 raw.as_ptr().write(val);
58 OwnedAlloc::from_raw(raw)
59 }
60 }
61}
62
63impl<T> UninitAlloc<T>
64 where
65 T: ?Sized,
66{
67 pub unsafe fn init_in_place<F>(self, init: F) -> OwnedAlloc<T>
75 where
76 F: FnOnce(&mut T),
77 {
78 let mut raw = self.into_raw();
79 init(raw.as_mut());
80 OwnedAlloc::from_raw(raw)
81 }
82
83 pub unsafe fn from_raw(nnptr: NonNull<T>) -> Self {
89 Self { nnptr, _marker: PhantomData }
90 }
91
92 pub fn raw(&self) -> NonNull<T> {
94 self.nnptr
95 }
96
97 pub fn into_raw(self) -> NonNull<T> {
99 let nnptr = self.nnptr;
100 mem::forget(self);
101 nnptr
102 }
103}
104
105impl<T> Drop for UninitAlloc<T>
106 where
107 T: ?Sized,
108{
109 fn drop(&mut self) {
110 unsafe {
111 let layout = Layout::for_value(self.nnptr.as_ref());
112
113 if layout.size() != 0 {
114 dealloc(self.nnptr.cast().as_ptr(), layout);
115 }
116 }
117 }
118}
119
120impl<T> fmt::Debug for UninitAlloc<T>
121 where
122 T: ?Sized,
123{
124 fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
125 write!(fmtr, "{:?}", self.nnptr)
126 }
127}
128
129impl<T> From<RawVec<T>> for UninitAlloc<[T]> {
130 fn from(alloc: RawVec<T>) -> Self {
131 Self { nnptr: alloc.into_raw_slice(), _marker: PhantomData }
132 }
133}
134
135unsafe impl<T> Send for UninitAlloc<T> where T: ?Sized + Send {}
136
137unsafe impl<T> Sync for UninitAlloc<T> where T: ?Sized + Sync {}
138
139#[cfg(test)]
140mod test {
141 use super::UninitAlloc;
142
143 #[test]
144 fn into_from_raw() {
145 let alloc = UninitAlloc::<usize>::new();
146 let raw_borrowed = alloc.raw();
147 let raw = alloc.into_raw();
148
149 assert_eq!(raw, raw_borrowed);
150
151 let alloc = unsafe { UninitAlloc::from_raw(raw) };
152 assert_eq!(alloc.raw(), raw_borrowed);
153 }
154}