1pub use aliu::*;
2use alloc::alloc::Layout;
3use core::cell::Cell;
4use core::ptr::NonNull;
5
6#[repr(C)]
7pub struct HeapArrayData<Tag, Item>
8where
9 Item: Copy,
10{
11 tag: Tag,
12 items: [Item],
13}
14
15pub struct HeapArray<Tag, Item, A>
16where
17 Item: Copy,
18 A: Allocator,
19{
20 data: NonNull<HeapArrayData<Tag, Item>>,
21 alloc: A,
22}
23
24impl<Tag, Item> HeapArray<Tag, Item, Global>
25where
26 Item: Copy,
27{
28 #[inline]
29 pub fn new(tag: Tag, items: &[Item]) -> Self {
30 return Self::with_allocator(tag, items, Global);
31 }
32}
33
34impl<Tag, Item, A> HeapArray<Tag, Item, A>
35where
36 Item: Copy,
37 A: Allocator,
38{
39 fn layout(len: usize) -> Layout {
40 #[repr(C)]
41 pub struct Data<Tag, Item>
42 where
43 Item: Copy,
44 {
45 t: Tag,
46 i: Item,
47 }
48
49 let align = core::mem::align_of::<Data<Tag, Item>>();
50 let size = core::mem::size_of::<Data<Tag, Item>>();
51 let item_size = core::mem::size_of::<Item>();
52 let size = size - item_size + item_size * len;
53
54 return unsafe { Layout::from_size_align_unchecked(size, align) };
55 }
56
57 pub fn with_allocator(tag: Tag, items: &[Item], a: A) -> Self {
58 unsafe {
59 let ptr = match a.allocate(Self::layout(items.len())) {
60 Ok(mut p) => p.as_mut(),
61 Err(e) => panic!("rip"),
62 };
63
64 let ptr = ptr.as_mut_ptr() as *mut Item;
65 let data = core::slice::from_raw_parts_mut(ptr, items.len());
66 let data = data as *mut [Item] as *mut HeapArrayData<Tag, Item>;
67
68 let data = &mut *data;
69
70 core::ptr::write(&mut data.tag, tag);
71 data.items.copy_from_slice(items);
72
73 let data = NonNull::new_unchecked(data);
74
75 return Self { data, alloc: a };
76 };
77 }
78}
79
80impl<Tag, Item, A> Drop for HeapArray<Tag, Item, A>
81where
82 Item: Copy,
83 A: Allocator,
84{
85 fn drop(&mut self) {
86 unsafe {
87 let data = self.data.as_mut();
88 let layout = Self::layout(data.items.len());
89
90 core::ptr::drop_in_place(data);
91
92 let data = self.data.cast::<u8>();
93 self.alloc.deallocate(data, layout);
94 }
95 }
96}
97
98impl<Tag, Item, A> core::ops::Deref for HeapArray<Tag, Item, A>
99where
100 Item: Copy,
101 A: Allocator,
102{
103 type Target = HeapArrayData<Tag, Item>;
104
105 fn deref(&self) -> &Self::Target {
106 unsafe {
107 return self.data.as_ref();
108 }
109 }
110}
111
112impl<Tag, Item, A> core::ops::DerefMut for HeapArray<Tag, Item, A>
113where
114 Item: Copy,
115 A: Allocator,
116{
117 fn deref_mut(&mut self) -> &mut Self::Target {
118 unsafe {
119 return self.data.as_mut();
120 }
121 }
122}
123
124#[test]
125fn heap_array() {
126 let mut a = Pod::new();
127
128 for i in 0..100 {
129 a.push(100 - i);
130 }
131
132 let array = HeapArray::new(Box::new(12), &a);
133
134 assert_eq!(&*a, &array.items);
135}