1#[cfg(test)]
2mod tests {
3 use crate::HeapVec;
4 #[test]
5 fn size_ok() {
6 use std::mem::size_of;
7 assert_eq!(size_of::<*mut u8>(), size_of::<HeapVec<u8>>());
8 }
9
10 #[test]
11 fn insert_test() {
12 let mut hv: crate::HeapVec<u8> = crate::HeapVec::new();
13 assert_eq!(hv.len(), 0);
14 hv.push(0);
15 assert_eq!(hv.len(), 1);
16
17 hv.push(1);
18 assert_eq!(hv.len(), 2);
19
20 let hvc = hv.clone();
21
22
23 assert_eq!(hv[0], 0);
24 assert_eq!(hv[1], 1);
25
26 assert_eq!(hv.pop(), Some(1));
27 assert_eq!(hv.len(), 1);
28 assert_eq!(hv.pop(), Some(0));
29 assert_eq!(hv.len(), 0);
30 assert_eq!(hv.pop(), None);
31
32 assert_eq!(hvc[..], [0, 1]);
33 }
34
35 #[test]
36 #[should_panic(expected = "droppanic.drop()")]
37 fn test_drop_panic() {
38 struct DropPanic {
41 test: u8
42 };
43 impl Drop for DropPanic {
46 fn drop(&mut self) {
47 panic!("droppanic.drop()");
48
49 }
50 }
51
52 let mut v = HeapVec::new();
53 v.push(DropPanic{test: 0});
54 }
55}
56
57use std::marker::PhantomData;
58use std::mem;
59
60struct Unique<T> {
61 ptr: *const T, _marker: PhantomData<T>, }
64
65unsafe impl<T: Send> Send for Unique<T> {}
68unsafe impl<T: Sync> Sync for Unique<T> {}
69
70impl<T> Unique<T> {
71 pub fn new(ptr: *mut T) -> Self {
72 Unique { ptr: ptr, _marker: PhantomData }
73 }
74
75 pub fn as_ptr(&self) -> *mut T {
76 self.ptr as *mut T
77 }
78
79 pub fn is_null(&self) -> bool {
80 self.ptr as usize == 0
81 }
82}
83
84use std::alloc;
85
86pub struct HeapVec<T> {
87 ptr: Unique<T>,
88}
89
90impl<T> HeapVec<T> {
91 pub fn new() -> Self {
92 assert!(std::mem::size_of::<T>() != 0, "We're not ready to handle types with size 0!");
93 Self { ptr: Unique::new(0 as *mut T)}
94 }
95
96 pub fn raw_ptr(&self) -> *const T {
97 (self.ptr.as_ptr() as usize + Self::get_offset()) as *mut T
98 }
99
100 const fn get_offset() -> usize {
101 ((mem::size_of::<usize>()*2 + mem::align_of::<T>() - 1) / mem::align_of::<T>()) * mem::align_of::<T>()
105 }
106
107 fn get_offset_of(&self, index: usize) -> *mut T {
108 (self.ptr.as_ptr() as usize + Self::get_offset() + mem::size_of::<T>() * index) as *mut T
109 }
110
111 fn capacity(&self) -> usize {
112 if self.ptr.is_null() {
113 0
114 } else {
115 unsafe {
116 *(self.ptr.as_ptr() as *const usize)
117 }
118 }
119 }
120
121 pub fn len(&self) -> usize {
122 if self.ptr.is_null() {
123 0
124 } else {
125 unsafe {
126 *((self.ptr.as_ptr() as usize + mem::size_of::<usize>()) as *const usize)
127 }
128 }
129 }
130
131 fn get_cap_mut(&mut self) -> &mut usize {
132 unsafe {
133 &mut*(self.ptr.as_ptr() as *mut usize)
134 }
135 }
136
137 fn get_len_mut(&mut self) -> &mut usize {
138 unsafe {
139 &mut *((self.ptr.as_ptr() as usize + mem::size_of::<usize>()) as *mut usize)
140 }
141 }
142
143 fn grow(&mut self) {
144 unsafe {
145 let cap_size = Self::get_offset();
146 let elem_size = mem::size_of::<T>();
147 let align = std::cmp::max(mem::align_of::<T>(), mem::align_of::<usize>());
148
149
150 if self.ptr.is_null() {
151 let new_num_bytes = cap_size + elem_size;
152
153 let ptr = alloc::alloc(alloc::Layout::from_size_align(new_num_bytes, align).expect("Couldn't create layout!"));
154
155 if ptr.is_null() {
156 panic!("Allocation failed!");
157 }
158
159 self.ptr = Unique::new(ptr as *mut T);
160 *self.get_cap_mut() = 1;
161
162 } else {
163 let old_cap = self.capacity();
164 let new_cap = old_cap * 2;
165 let old_num_bytes = cap_size + old_cap*elem_size;
166 let new_num_bytes = cap_size + 2*old_cap*elem_size;
167
168 let ptr = alloc::realloc(self.ptr.as_ptr() as *mut u8,
169 alloc::Layout::from_size_align(old_num_bytes, align).expect("Couldn't create layout!"),
170 new_num_bytes
171 );
172
173 self.ptr = Unique::new(ptr as *mut T);
174 *self.get_cap_mut() = new_cap;
175 };
176 }
177 }
178
179 pub fn push(&mut self, elem: T) {
180 if self.len() == self.capacity() {
181 self.grow();
182 }
183
184 unsafe {
185 std::ptr::write(self.get_offset_of(self.len()), elem);
186 }
187
188 *self.get_len_mut() += 1;
189 }
190
191 pub fn pop(&mut self) -> Option<T> {
192 if self.len() == 0 {
193 None
194 } else {
195 *self.get_len_mut() -= 1;
196 unsafe {
197 Some(std::ptr::read(self.get_offset_of(self.len())))
198 }
199 }
200 }
201
202 pub fn insert(&mut self, index: usize, elem: T) {
203 assert!(index <= self.len(), "index out of bounds");
204 if self.capacity() == self.len() { self.grow(); }
205
206 unsafe {
207 if index < self.len() {
208 std::ptr::copy(self.get_offset_of(index),
210 self.get_offset_of(index + 1),
211 self.len() - index);
212 }
213 std::ptr::write(self.get_offset_of(index), elem);
214 }
215 *self.get_len_mut() += 1;
216 }
217
218 pub fn remove(&mut self, index: usize) -> T {
219 assert!(index < self.len(), "index out of bounds");
221 unsafe {
222 *self.get_len_mut() -= 1;
223 let result = std::ptr::read(self.get_offset_of(index));
224 std::ptr::copy(self.get_offset_of(index + 1),
225 self.get_offset_of(index),
226 self.len() - index);
227 result
228 }
229 }
230}
231
232impl<T> Drop for HeapVec<T> {
233 fn drop(&mut self) {
234 if !self.ptr.is_null() {
235 while let Some(_) = self.pop() { }
236
237 let align = std::cmp::max(mem::align_of::<T>(), mem::align_of::<usize>());
238 let elem_size = mem::size_of::<T>();
239 let cap_size = Self::get_offset();
240 let num_bytes = cap_size + elem_size * self.capacity();
241 unsafe {
242 alloc::dealloc(self.ptr.as_ptr() as *mut _, alloc::Layout::from_size_align(num_bytes, align).expect("Couldn't create layout!"));
243 }
244 }
245 }
246}
247
248use std::ops::Deref;
249impl<T> Deref for HeapVec<T> {
250 type Target = [T];
251 fn deref(&self) -> &[T] {
252 unsafe {
253 std::slice::from_raw_parts(self.get_offset_of(0), self.len())
254 }
255 }
256}
257use std::ops::DerefMut;
258impl<T> DerefMut for HeapVec<T> {
259 fn deref_mut(&mut self) -> &mut [T] {
260 unsafe {
261 std::slice::from_raw_parts_mut(self.get_offset_of(0), self.len())
262 }
263 }
264}
265
266impl<T: Clone> Clone for HeapVec<T> {
267 fn clone(&self) -> Self {
268 unsafe {
269 let cap_size = Self::get_offset();
270 let elem_size = mem::size_of::<T>();
271 let align = std::cmp::max(mem::align_of::<T>(), mem::align_of::<usize>());
272 let num_bytes = cap_size + elem_size * self.capacity();
273
274 let ptr = alloc::alloc(alloc::Layout::from_size_align(num_bytes, align).expect("Couldn't create layout!"));
275
276 if ptr.is_null() {
277 panic!("Allocation failed!");
278 }
279
280 let mut new_hv = Self{ptr: Unique::new(ptr as *mut T)};
281 *new_hv.get_cap_mut() = self.capacity();
282 for v in self.iter() {
283 new_hv.push(v.clone());
284 }
285 new_hv
286 }
287 }
288}
289
290
291