1use crate::region::Region;
2
3use std::alloc::Layout;
4use std::ops;
5
6pub struct Header {
7 drop_fn: Option<fn(*mut u8)>,
9}
10
11pub struct Handle<T> {
13 ptr: *mut T,
14}
15
16impl<T> Clone for Handle<T> {
17 fn clone(&self) -> Self {
18 Self { ptr: self.ptr }
19 }
20}
21
22impl<T> Copy for Handle<T> {}
23
24impl<T> Handle<T> {
25 pub fn raw(self) -> RawHandle {
27 RawHandle {
28 ptr: self.ptr as *mut u8,
29 }
30 }
31}
32
33pub struct RawHandle {
36 ptr: *mut u8,
37}
38
39impl Clone for RawHandle {
40 fn clone(&self) -> Self {
41 Self { ptr: self.ptr }
42 }
43}
44
45impl Copy for RawHandle {}
46
47impl<T> From<Handle<T>> for RawHandle {
48 fn from(handle: Handle<T>) -> Self {
49 handle.raw()
50 }
51}
52
53impl RawHandle {
54 pub unsafe fn trust_type<T>(self) -> Handle<T> {
59 Handle {
60 ptr: self.ptr as *mut T,
61 }
62 }
63}
64
65#[derive(Default)]
67pub struct RawDynVec<R: Region<Header>> {
68 region: R,
69}
70
71impl<R: Region<Header>> Drop for RawDynVec<R> {
72 fn drop(&mut self) {
73 self.clear();
74 }
75}
76
77impl<R: Region<Header>, T> ops::Index<Handle<T>> for RawDynVec<R> {
78 type Output = T;
79
80 fn index(&self, index: Handle<T>) -> &Self::Output {
81 self.get(index)
82 }
83}
84
85impl<R: Region<Header>, T> ops::IndexMut<Handle<T>> for RawDynVec<R> {
86 fn index_mut(&mut self, index: Handle<T>) -> &mut Self::Output {
87 self.get_mut(index)
88 }
89}
90
91impl<R: Region<Header>> RawDynVec<R> {
92 pub fn with_region(region: R) -> Self {
94 Self { region }
95 }
96
97 pub fn count(&self) -> usize {
99 self.region.count()
100 }
101
102 pub fn try_insert<T>(&mut self, item: T) -> Result<Handle<T>, T> {
106 let layout = Layout::new::<T>();
107
108 let drop_fn: Option<fn(*mut u8)> = if std::mem::needs_drop::<T>() {
109 Some(|ptr: *mut u8| unsafe { std::ptr::drop_in_place(ptr as *mut T) })
110 } else {
111 None
112 };
113
114 match unsafe { self.insert_raw(layout, drop_fn) } {
115 Ok(handle) => {
116 unsafe {
117 handle.ptr.cast::<T>().write(item);
118 Ok(handle.trust_type::<T>())
119 }
120 },
121
122 Err(()) => Err(item),
123 }
124 }
125
126 pub fn clear(&mut self) {
128 for (ptr, header) in self.region.deallocate_all() {
129 if let Some(drop_fn) = header.drop_fn {
130 drop_fn(ptr)
132 }
133 }
134 }
135
136 pub fn insert<T>(&mut self, item: T) -> Handle<T> {
141 match self.try_insert(item) {
142 Ok(handle) => handle,
143 Err(_) => {
144 panic!("Failed to allocate the item");
145 }
146 }
147 }
148
149 pub unsafe fn insert_raw(
158 &mut self,
159 layout: Layout,
160 drop_fn: Option<fn(*mut u8)>,
161 ) -> Result<RawHandle, ()> {
162 let header = Header {
163 drop_fn,
164 };
165
166 match self.region.allocate(layout, header) {
167 Ok(ptr) => {
168 Ok(RawHandle { ptr, })
169 }
170
171 Err(_) => Err(()),
172 }
173 }
174
175 pub fn remove<T>(&mut self, handle: Handle<T>) -> Result<T, ()> {
178 if let Some(_) = self.region.deallocate(handle.ptr as *mut u8) {
179 let item = unsafe { handle.ptr.read() };
182
183 Ok(item)
186 } else {
187 Err(())
188 }
189 }
190
191 pub fn remove_raw(&mut self, handle: RawHandle) -> Result<(), ()> {
197 if let Some(header) = self.region.deallocate(handle.ptr) {
198 if let Some(drop_fn) = header.drop_fn {
199 drop_fn(handle.ptr);
201 }
202
203 Ok(())
204 } else {
205 Err(())
206 }
207 }
208
209 pub fn get_ptr<T>(&self, handle: Handle<T>) -> *const T {
214 if self.region.has_allocated(handle.ptr as *mut u8) {
215 handle.ptr
216 } else {
217 std::ptr::null()
218 }
219 }
220
221 pub fn get_mut_ptr<T>(&self, handle: Handle<T>) -> *mut T {
226 if self.region.has_allocated(handle.ptr as *mut u8) {
227 handle.ptr
228 } else {
229 std::ptr::null_mut()
230 }
231 }
232
233 pub fn get_ptr_raw(&mut self, handle: RawHandle) -> *const u8 {
238 if self.region.has_allocated(handle.ptr) {
239 handle.ptr
240 } else {
241 std::ptr::null()
242 }
243 }
244
245 pub fn get_mut_ptr_raw(&mut self, handle: RawHandle) -> *mut u8 {
250 if self.region.has_allocated(handle.ptr) {
251 handle.ptr
252 } else {
253 std::ptr::null_mut()
254 }
255 }
256
257 pub fn try_get<T>(&self, handle: Handle<T>) -> Option<&T> {
259 unsafe { std::mem::transmute(self.get_ptr(handle)) }
262 }
263
264 pub fn try_get_mut<T>(&mut self, handle: Handle<T>) -> Option<&mut T> {
266 unsafe { std::mem::transmute(self.get_mut_ptr(handle)) }
267 }
268
269 pub fn get<T>(&self, handle: Handle<T>) -> &T {
274 self.try_get(handle).expect("Invalid handle")
275 }
276
277 pub fn get_mut<T>(&mut self, handle: Handle<T>) -> &mut T {
282 self.try_get_mut(handle).expect("Invalid handle")
283 }
284}
285
286#[cfg(test)]
287#[test]
288fn properly_dropped() {
289 use std::cell::Cell;
290 use std::rc::Rc;
291
292 use crate::region::block::Block;
293
294 let drop_count = Rc::new(Cell::new(0u16));
295 struct DropCheck(Rc<Cell<u16>>);
296 impl Drop for DropCheck {
297 fn drop(&mut self) {
298 self.0.set(self.0.get() + 1);
299 }
300 }
301
302 {
303 let mut vec = RawDynVec::with_region(Block::new(2048));
304
305 for _ in 0..100 {
306 vec.insert(DropCheck(Rc::clone(&drop_count)));
307 }
308
309 }
311
312 assert_eq!(drop_count.get(), 100);
313}
314
315#[cfg(test)]
316#[test]
317fn normal_use() {
318 use crate::region::block::Block;
319
320 let mut vec = RawDynVec::with_region(Block::new(2048));
321
322 let h_i32 = vec.insert(5i32);
323 let h_vec = vec.insert(vec![1u8, 2, 3]);
324
325 assert_eq!(vec[h_i32], 5i32);
326 assert_eq!(vec[h_vec][1], 2u8);
327
328 vec[h_vec].push(8);
329
330 assert_eq!(vec.get(h_vec).last(), Some(&8));
331
332 let other_vec = vec.remove(h_vec).unwrap();
333
334 assert_eq!(&other_vec[..], &[1, 2, 3, 8][..]);
335
336 assert_eq!(vec.try_get(h_vec), None);
337}