3 We've actually reached an interesting situation here: we've duplicated the logic
4 for specifying a buffer and freeing its memory in Vec and IntoIter. Now that
5 we've implemented it and identified *actual* logic duplication, this is a good
6 time to perform some logic compression.
8 We're going to abstract out the `(ptr, cap)` pair and give them the logic for
9 allocating, growing, and freeing:
19 assert!(mem::size_of::<T>() != 0, "TODO: implement ZST support");
21 RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: 0 }
28 let align = mem::align_of::<T>();
29 let elem_size = mem::size_of::<T>();
31 let (new_cap, ptr) = if self.cap == 0 {
32 let ptr = heap::allocate(elem_size, align);
35 let new_cap = 2 * self.cap;
36 let ptr = heap::reallocate(*self.ptr as *mut _,
43 // If allocate or reallocate fail, we'll get `null` back
44 if ptr.is_null() { oom() }
46 self.ptr = Unique::new(ptr as *mut _);
53 impl<T> Drop for RawVec<T> {
56 let align = mem::align_of::<T>();
57 let elem_size = mem::size_of::<T>();
58 let num_bytes = elem_size * self.cap;
60 heap::deallocate(*self.ptr as *mut _, num_bytes, align);
67 And change Vec as follows:
76 fn ptr(&self) -> *mut T { *self.buf.ptr }
78 fn cap(&self) -> usize { self.buf.cap }
80 pub fn new() -> Self {
81 Vec { buf: RawVec::new(), len: 0 }
84 // push/pop/insert/remove largely unchanged:
85 // * `self.ptr -> self.ptr()`
86 // * `self.cap -> self.cap()`
87 // * `self.grow -> self.buf.grow()`
90 impl<T> Drop for Vec<T> {
92 while let Some(_) = self.pop() {}
93 // deallocation is handled by RawVec
98 And finally we can really simplify IntoIter:
102 _buf: RawVec<T>, // we don't actually care about this. Just need it to live.
107 // next and next_back literally unchanged since they never referred to the buf
109 impl<T> Drop for IntoIter<T> {
111 // only need to ensure all our elements are read;
112 // buffer will clean itself up afterwards.
113 for _ in &mut *self {}
118 pub fn into_iter(self) -> IntoIter<T> {
120 // need to use ptr::read to unsafely move the buf out since it's
121 // not Copy, and Vec implements Drop (so we can't destructure it).
122 let buf = ptr::read(&self.buf);
128 end: buf.ptr.offset(len as isize),