nomvec/
lib.rs

1use std::alloc::{self, Layout};
2use std::marker::PhantomData;
3use std::mem;
4use std::ops::{Deref, DerefMut};
5use std::ptr::{self, NonNull};
6
7struct RawVec<T> {
8    ptr: NonNull<T>,
9    cap: usize,
10    _marker: PhantomData<T>,
11}
12
13impl<T> RawVec<T> {
14    fn new() -> Self {
15        let cap = if mem::size_of::<T>() == 0 {
16            ::std::usize::MAX
17        } else {
18            0
19        };
20        // NonNull::dangling() doubles as "unallocated" and "zero-sized allocation"
21        RawVec {
22            ptr: NonNull::dangling(),
23            cap,
24            _marker: PhantomData,
25        }
26    }
27
28    // unchanged from Vec
29    fn grow(&mut self) {
30        // since we set the capacity to usize::MAX when elem_size is
31        // 0, getting to here necessarily means the Vec is overfull.
32        assert!(mem::size_of::<T>() != 0, "capacity overflow");
33
34        let (new_cap, new_layout) = if self.cap == 0 {
35            (1, Layout::array::<T>(1).unwrap())
36        } else {
37            // this cant overflow because we ensure self.cap <= isize::MAX
38            let new_cap = self.cap * 2;
39            (new_cap, Layout::array::<T>(new_cap).unwrap())
40        };
41
42        assert!(
43            new_layout.size() <= ::std::isize::MAX as usize,
44            "Allocation too large"
45        );
46
47        let new_ptr = if self.cap == 0 {
48            unsafe { alloc::alloc(new_layout) }
49        } else {
50            let old_layout = Layout::array::<T>(self.cap).unwrap();
51            let old_ptr = self.ptr.as_ptr() as *mut u8;
52            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
53        };
54
55        // if allocation fails, `new_ptr` will be null in which case we will abort
56        self.ptr = match NonNull::new(new_ptr as *mut _) {
57            Some(p) => p,
58            None => alloc::handle_alloc_error(new_layout),
59        };
60        self.cap = new_cap;
61    }
62}
63
64impl<T> Drop for RawVec<T> {
65    fn drop(&mut self) {
66        if self.cap != 0 {
67            let elem_size = mem::size_of::<T>();
68
69            // don't free zero-sized allocations, as they were never allocated.
70            if self.cap != 0 && elem_size != 0 {
71                let align = mem::align_of::<T>();
72                let num_bytes = elem_size * self.cap;
73                let layout = Layout::from_size_align(num_bytes, align).unwrap();
74                unsafe {
75                    alloc::dealloc(self.ptr.as_ptr() as *mut _, layout);
76                }
77            }
78        }
79    }
80}
81
82pub struct NomVec<T> {
83    buf: RawVec<T>,
84    len: usize,
85}
86
87impl<T> NomVec<T> {
88    fn ptr(&self) -> *mut T {
89        self.buf.ptr.as_ptr()
90    }
91
92    fn cap(&self) -> usize {
93        self.buf.cap
94    }
95
96    pub fn new() -> Self {
97        Self {
98            buf: RawVec::new(),
99            len: 0,
100        }
101    }
102
103    pub fn push(&mut self, elem: T) {
104        if self.len == self.cap() {
105            self.buf.grow();
106        }
107        unsafe {
108            ptr::write(self.ptr().offset(self.len as isize), elem);
109        }
110        // Can't fail, we'll OOM first.
111        self.len += 1;
112    }
113
114    pub fn pop(&mut self) -> Option<T> {
115        if self.len == 0 {
116            None
117        } else {
118            self.len -= 1;
119            unsafe { Some(ptr::read(self.ptr().offset(self.len as isize))) }
120        }
121    }
122
123    pub fn len(&self) -> usize {
124        self.len
125    }
126
127    pub fn insert(&mut self, index: usize, elem: T) {
128        // Note: `<=` because it's valid to insert after everything
129        // which would be equivalent to push.
130        assert!(index <= self.len, "index out of bounds");
131        if self.cap() == self.len {
132            self.buf.grow();
133        }
134        unsafe {
135            if index < self.len {
136                ptr::copy(
137                    self.ptr().offset(index as isize),
138                    self.ptr().offset(index as isize + 1),
139                    self.len - index,
140                );
141            }
142            ptr::write(self.ptr().offset(index as isize), elem);
143            self.len += 1;
144        }
145    }
146
147    pub fn remove(&mut self, index: usize) -> T {
148        assert!(index < self.len, "index out of bounds");
149        unsafe {
150            self.len -= 1;
151            let result = ptr::read(self.ptr().offset(index as isize));
152            ptr::copy(
153                self.ptr().offset(index as isize + 1),
154                self.ptr().offset(index as isize),
155                self.len - index,
156            );
157            result
158        }
159    }
160
161    pub fn drain(&mut self) -> Drain<T> {
162        unsafe {
163            let iter = RawValIter::new(&self);
164            // this is a mem::forget safety thing. If Drain is forgotten, we just
165            // leak the whole Vec's contents. Also we need to do this *eventually*
166            // anyway, so why not do it now?
167            self.len = 0;
168            Drain {
169                iter,
170                vec: PhantomData,
171            }
172        }
173    }
174}
175
176impl<T> Drop for NomVec<T> {
177    fn drop(&mut self) {
178        // deallocation is handled by RawVec
179        while let Some(_) = self.pop() {}
180    }
181}
182
183impl<T> Deref for NomVec<T> {
184    type Target = [T];
185    fn deref(&self) -> &[T] {
186        unsafe { ::std::slice::from_raw_parts(self.ptr(), self.len) }
187    }
188}
189
190impl<T> DerefMut for NomVec<T> {
191    fn deref_mut(&mut self) -> &mut [T] {
192        unsafe { ::std::slice::from_raw_parts_mut(self.ptr(), self.len) }
193    }
194}
195
196impl<T> IntoIterator for NomVec<T> {
197    type Item = T;
198    type IntoIter = IntoIter<T>;
199
200    fn into_iter(self) -> IntoIter<T> {
201        unsafe {
202            // need to use ptr::read to unsafely move the buf out since it's
203            // not Copy, and Vec implements Drop (so we can't destructure it).
204            let iter = RawValIter::new(&self);
205            let buf = ptr::read(&self.buf);
206            mem::forget(self);
207            IntoIter { iter, _buf: buf }
208        }
209    }
210}
211
212struct RawValIter<T> {
213    start: *const T,
214    end: *const T,
215}
216
217impl<T> RawValIter<T> {
218    // unsafe to construct because it has no associated lifetimes.
219    // This is necessary to store a RawValIter in the same struct as
220    // its actual allocation. OK since it's a private implementation
221    // detail.
222    unsafe fn new(slice: &[T]) -> Self {
223        RawValIter {
224            start: slice.as_ptr(),
225            end: if mem::size_of::<T>() == 0 {
226                ((slice.as_ptr() as usize) + slice.len()) as *const _
227            } else if slice.len() == 0 {
228                // if `len = 0`, then this is not actually allocated memory.
229                // Need to avoid offsetting because that will give wrong
230                // information to LLVM via GEP.
231                slice.as_ptr()
232            } else {
233                slice.as_ptr().offset(slice.len() as isize)
234            },
235        }
236    }
237}
238
239impl<T> Iterator for RawValIter<T> {
240    type Item = T;
241    fn next(&mut self) -> Option<T> {
242        if self.start == self.end {
243            None
244        } else {
245            unsafe {
246                let result = ptr::read(self.start);
247                self.start = if mem::size_of::<T>() == 0 {
248                    (self.start as usize + 1) as *const _
249                } else {
250                    self.start.offset(1)
251                };
252                Some(result)
253            }
254        }
255    }
256
257    fn size_hint(&self) -> (usize, Option<usize>) {
258        let len =
259            (self.end as usize - self.start as usize) / mem::size_of::<T>();
260        (len, Some(len))
261    }
262}
263
264impl<T> DoubleEndedIterator for RawValIter<T> {
265    fn next_back(&mut self) -> Option<T> {
266        if self.start == self.end {
267            None
268        } else {
269            unsafe {
270                self.end = self.end.offset(-1);
271                Some(ptr::read(self.end))
272            }
273        }
274    }
275}
276
277pub struct IntoIter<T> {
278    _buf: RawVec<T>,
279    iter: RawValIter<T>,
280}
281
282impl<T> Iterator for IntoIter<T> {
283    type Item = T;
284    fn next(&mut self) -> Option<T> {
285        self.iter.next()
286    }
287
288    fn size_hint(&self) -> (usize, Option<usize>) {
289        self.iter.size_hint()
290    }
291}
292
293impl<T> DoubleEndedIterator for IntoIter<T> {
294    fn next_back(&mut self) -> Option<T> {
295        self.iter.next_back()
296    }
297}
298
299impl<T> Drop for IntoIter<T> {
300    fn drop(&mut self) {
301        // only need to ensure all our elements are read;
302        // buffer will clean itself up afterwards.
303        for _ in &mut self.iter {}
304    }
305}
306
307pub struct Drain<'a, T: 'a> {
308    // Need to bound the lifetime here, so we do it with `&'a mut Vec<T>`
309    // because that's semantically what we contain. We're "just" calling
310    // `pop()` and `remove(0)`.
311    vec: PhantomData<&'a mut NomVec<T>>,
312    iter: RawValIter<T>,
313}
314
315impl<'a, T> Iterator for Drain<'a, T> {
316    type Item = T;
317    fn next(&mut self) -> Option<T> {
318        self.iter.next()
319    }
320    fn size_hint(&self) -> (usize, Option<usize>) {
321        self.iter.size_hint()
322    }
323}
324
325impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
326    fn next_back(&mut self) -> Option<T> {
327        self.iter.next_back()
328    }
329}
330
331impl<'a, T> Drop for Drain<'a, T> {
332    fn drop(&mut self) {
333        // pre-drain the iter
334        for _ in &mut self.iter {}
335    }
336}
337
338#[cfg(test)]
339mod tests {
340    use super::*;
341
342    #[test]
343    fn vec_push() {
344        let mut cv = NomVec::new();
345        cv.push(2);
346        assert_eq!(cv.len(), 1);
347        cv.push(3);
348        assert_eq!(cv.len(), 2);
349    }
350
351    #[test]
352    fn vec_iter() {
353        let mut cv = NomVec::new();
354        cv.push(2);
355        cv.push(3);
356        let mut accum = 0;
357        for x in cv.iter() {
358            accum += x;
359        }
360        assert_eq!(accum, 5);
361    }
362
363    #[test]
364    fn vec_into_iter() {
365        let mut cv = NomVec::new();
366        cv.push(2);
367        cv.push(3);
368        assert_eq!(cv.into_iter().collect::<Vec<i32>>(), vec![2, 3]);
369    }
370
371    #[test]
372    fn vec_into_double_ended_iter() {
373        let mut cv = NomVec::new();
374        cv.push(2);
375        cv.push(3);
376        assert_eq!(*cv.iter().next_back().unwrap(), 3);
377    }
378
379    #[test]
380    fn vec_pop() {
381        let mut cv = NomVec::new();
382        cv.push(2);
383        assert_eq!(cv.len(), 1);
384        cv.pop();
385        assert_eq!(cv.len(), 0);
386        assert!(cv.pop() == None);
387    }
388
389    #[test]
390    fn vec_insert() {
391        let mut cv: NomVec<i32> = NomVec::new();
392        cv.insert(0, 2); // test insert at end
393        cv.insert(0, 1); // test insert at beginning
394        assert_eq!(cv.pop().unwrap(), 2);
395    }
396
397    #[test]
398    fn vec_remove() {
399        let mut cv = NomVec::new();
400        cv.push(2);
401        assert_eq!(cv.remove(0), 2);
402        assert_eq!(cv.len(), 0);
403    }
404
405    #[test]
406    #[should_panic(expected = "index out of bounds")]
407    fn vec_cant_remove() {
408        let mut cv: NomVec<i32> = NomVec::new();
409        cv.remove(0);
410    }
411
412    #[test]
413    fn vec_drain() {
414        let mut cv = NomVec::new();
415        cv.push(1);
416        cv.push(2);
417        cv.push(3);
418        assert_eq!(cv.len(), 3);
419        {
420            let mut drain = cv.drain();
421            assert_eq!(drain.next().unwrap(), 1);
422            assert_eq!(drain.next_back().unwrap(), 3);
423        }
424        assert_eq!(cv.len(), 0);
425    }
426
427    #[test]
428    fn vec_zst() {
429        let mut v = NomVec::new();
430        for _i in 0..10 {
431            v.push(());
432        }
433        assert_eq!(v.len(), 10);
434
435        let mut count = 0;
436        for _ in v.into_iter() {
437            count += 1
438        }
439        assert_eq!(10, count);
440    }
441}