Skip to main content

lessvec/
lib.rs

1//! A minimal `Vec`-like collection implemented with manual allocation.
2//!
3//! This crate provides `LessVec<T>`, a small, educational reimplementation of
4//! `std::vec::Vec<T>` following patterns from the Rustonomicon. It's intended
5//! for learning and small use-cases, not as a drop-in replacement for `Vec`.
6//!
7//! # Examples
8//! ```
9//! use lessvec::LessVec;
10//!
11//! let mut v = LessVec::new();
12//! v.push(1);
13//! v.push(2);
14//! assert_eq!(&*v, &[1, 2]);
15//! assert_eq!(v.pop(), Some(2));
16//! ```
17//!
18//! See individual method docs for more examples.
19use std::{
20    alloc::{self, Layout},
21    marker::PhantomData,
22    mem,
23    ops::{Deref, DerefMut},
24    ptr::{self, NonNull},
25};
26
27mod macros;
28
29/// Re-exports a small "prelude" of the most commonly-used items.
30///
31/// The prelude provides:
32/// - `LessVec` — the vector type
33/// - `lessvec!` — the convenient macro (same syntax as `vec!`)
34///
35/// Bring them into scope with:
36///
37/// ```
38/// use lessvec::prelude::*;
39///
40/// let v = lessvec![1, 2, 3];
41/// assert_eq!(v.as_slice(), &[1, 2, 3]);
42/// ```
43pub mod prelude {
44    pub use crate::LessVec;
45    pub use crate::lessvec;
46}
47
48struct RawVec<T> {
49    ptr: NonNull<T>,
50    cap: usize,
51}
52
53unsafe impl<T: Send> Send for RawVec<T> {}
54unsafe impl<T: Sync> Sync for RawVec<T> {}
55
56impl<T> RawVec<T> {
57    fn new() -> Self {
58        let cap = if mem::size_of::<T>() == 0 {
59            usize::MAX
60        } else {
61            0
62        };
63
64        // `NonNull::dangling` doubles as "unallocated" and "zero-sized allocation"
65        RawVec {
66            ptr: NonNull::dangling(),
67            cap,
68        }
69    }
70
71    fn grow(&mut self) {
72        // since we set the capacity to usize::MAX when T has size 0, getting
73        // to here means Vec is overfull.
74        assert!(mem::size_of::<T>() != 0, "capacity overflow");
75
76        let (new_cap, new_layout) = if self.cap == 0 {
77            (1, Layout::array::<T>(1).unwrap())
78        } else {
79            // `new_cap` will not overflow because `self.cap <= isize::MAX`.
80            let new_cap = 2 * self.cap;
81
82            // `Layout::array` checks that the number of bytes is <= usize::MAX,
83            // but this is redundant since old_layout.size() <= isize::MAX,
84            // `unwrap` should never fail.
85            let new_layout = Layout::array::<T>(new_cap).unwrap();
86            (new_cap, new_layout)
87        };
88
89        // Ensure that the new allocation doesn't overflow; <= isize::MAX bytes.
90        assert!(
91            new_layout.size() <= isize::MAX as usize,
92            "Allocation too large"
93        );
94
95        let new_ptr = if self.cap == 0 {
96            unsafe { alloc::alloc(new_layout) }
97        } else {
98            let old_layout = Layout::array::<T>(self.cap).unwrap();
99            let old_ptr = self.ptr.as_ptr() as *mut u8;
100            unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) }
101        };
102
103        // new_ptr becomes null if allocation fails, abort.
104        self.ptr = match NonNull::new(new_ptr as *mut T) {
105            Some(p) => p,
106            None => alloc::handle_alloc_error(new_layout),
107        };
108
109        self.cap = new_cap;
110    }
111
112    fn grow_to(&mut self, new_cap: usize) {
113        if mem::size_of::<T>() == 0 {
114            return;
115        }
116        if new_cap <= self.cap {
117            return;
118        }
119
120        let new_layout = Layout::array::<T>(new_cap).unwrap();
121        assert!(
122            new_layout.size() <= isize::MAX as usize,
123            "Allocation too large"
124        );
125
126        let new_ptr = if self.cap == 0 {
127            unsafe { alloc::alloc(new_layout) }
128        } else {
129            let old_layout = Layout::array::<T>(self.cap).unwrap();
130            let old_tr = self.ptr.as_ptr() as *mut u8;
131            unsafe { alloc::realloc(old_tr, old_layout, new_layout.size()) }
132        };
133
134        self.ptr = match NonNull::new(new_ptr as *mut T) {
135            Some(p) => p,
136            None => alloc::handle_alloc_error(new_layout),
137        };
138
139        self.cap = new_cap;
140    }
141}
142
143impl<T> Drop for RawVec<T> {
144    fn drop(&mut self) {
145        if self.cap != 0 && std::mem::size_of::<T>() > 0 {
146            let layout = std::alloc::Layout::array::<T>(self.cap).unwrap();
147            unsafe {
148                std::alloc::dealloc(self.ptr.as_ptr() as *mut _, layout);
149            }
150        }
151    }
152}
153
154/// A minimal growable contiguous vector.
155///
156/// `LessVec<T>` stores elements in a heap buffer and supports a small set of
157/// `Vec`-like operations. Use the methods below to manipulate the collection.
158///
159/// # Examples
160///
161/// ```
162/// use lessvec::LessVec;
163///
164/// let mut v = LessVec::new();
165/// v.push(10);
166/// v.push(20);
167/// assert_eq!(v.len(), 2);
168/// assert!(!v.is_empty());
169/// assert!(v.capacity() >= 2);
170/// ```
171pub struct LessVec<T> {
172    buf: RawVec<T>,
173    len: usize,
174}
175
176unsafe impl<T: Send> Send for LessVec<T> {}
177unsafe impl<T: Sync> Sync for LessVec<T> {}
178
179impl<T> Default for LessVec<T> {
180    fn default() -> Self {
181        Self::new()
182    }
183}
184
185impl<T> LessVec<T> {
186    fn ptr(&self) -> *mut T {
187        self.buf.ptr.as_ptr()
188    }
189
190    fn cap(&self) -> usize {
191        self.buf.cap
192    }
193
194    /// Creates a new, empty `LessVec`.
195    ///
196    /// # Examples
197    ///
198    /// ```
199    /// use lessvec::LessVec;
200    /// let v: LessVec<i32> = LessVec::new();
201    /// assert_eq!(v.len(), 0);
202    /// ```
203    pub fn new() -> Self {
204        LessVec {
205            buf: RawVec::new(),
206            len: 0,
207        }
208    }
209
210    /// Returns the number of elements in the vector.
211    ///
212    /// # Examples
213    ///
214    /// ```
215    /// use lessvec::LessVec;
216    /// let mut v = LessVec::new();
217    /// v.push(1);
218    /// assert_eq!(v.len(), 1);
219    /// ```
220    pub fn len(&self) -> usize {
221        self.len
222    }
223
224    /// Returns `true` if the vector contains no elements.
225    ///
226    /// # Examples
227    ///
228    /// ```
229    /// use lessvec::LessVec;
230    /// let mut v = LessVec::new();
231    /// assert!(v.is_empty());
232    /// v.push(1);
233    /// assert!(!v.is_empty());
234    /// ```
235    pub fn is_empty(&self) -> bool {
236        self.len == 0
237    }
238
239    /// Returns the number of elements the `LessVec` can hold without reallocating.
240    ///
241    /// Note: capacity may be larger than the number of elements. Calling
242    /// `reserve` or `reserve_exact` increases capacity.
243    ///
244    /// # Examples
245    ///
246    /// ```
247    /// use lessvec::LessVec;
248    /// let mut v: LessVec<i32> = LessVec::new();
249    /// v.reserve(5);
250    /// assert!(v.capacity() >= 5);
251    /// ```
252    pub fn capacity(&self) -> usize {
253        self.cap()
254    }
255
256    /// Clears the vector, removing all values.
257    ///
258    /// This drops each element in the vector.
259    ///
260    /// # Examples
261    ///
262    /// ```
263    /// use lessvec::LessVec;
264    /// let mut v = LessVec::new();
265    /// v.push(1);
266    /// v.clear();
267    /// assert!(v.is_empty());
268    /// ```
269    pub fn clear(&mut self) {
270        while self.pop().is_some() {}
271    }
272
273    /// Returns a slice containing all elements of the vector.
274    ///
275    /// # Examples
276    ///
277    /// ```
278    /// use lessvec::LessVec;
279    /// let mut v = LessVec::new();
280    /// v.push(1);
281    /// assert_eq!(v.as_slice(), &[1]);
282    /// ```
283    pub fn as_slice(&self) -> &[T] {
284        self
285    }
286
287    /// Returns a mutable slice containing all elements of the vector.
288    ///
289    /// # Examples
290    ///
291    /// ```
292    /// use lessvec::LessVec;
293    /// let mut v = LessVec::new();
294    /// v.push(1);
295    /// v.as_mut_slice()[0] = 2;
296    /// assert_eq!(v.as_slice(), &[2]);
297    /// ```
298    pub fn as_mut_slice(&mut self) -> &mut [T] {
299        &mut *self
300    }
301
302    /// Ensures the `LessVec` can hold at least `additional` more elements without reallocating.
303    ///
304    /// This grows capacity exponentially where necessary.
305    ///
306    /// # Examples
307    ///
308    /// ```
309    /// use lessvec::LessVec;
310    /// let mut v: LessVec<i32> = LessVec::new();
311    /// v.reserve(10);
312    /// assert!(v.capacity() >= 10);
313    /// ```
314    pub fn reserve(&mut self, additional: usize) {
315        let required = self.len.checked_add(additional).expect("capacity overflow");
316        if self.cap() >= required {
317            return;
318        }
319        while self.cap() < required {
320            self.buf.grow();
321        }
322    }
323
324    /// Ensures the `LessVec` has capacity for exactly `additional` more elements (no fewer).
325    ///
326    /// Unlike `reserve`, this attempts to allocate the exact requested capacity in one go.
327    ///
328    /// # Examples
329    ///
330    /// ```
331    /// use lessvec::LessVec;
332    /// let mut v: LessVec<i32> = LessVec::new();
333    /// v.reserve_exact(3);
334    /// assert!(v.capacity() >= 3);
335    /// ```
336    pub fn reserve_exact(&mut self, additional: usize) {
337        let required = self.len.checked_add(additional).expect("capacity overflow");
338        if self.cap() >= required {
339            return;
340        }
341        self.buf.grow_to(required);
342    }
343
344    /// Appends an element to the back of the collection.
345    ///
346    /// # Examples
347    ///
348    /// ```
349    /// use lessvec::LessVec;
350    /// let mut v = LessVec::new();
351    /// v.push(5);
352    /// assert_eq!(v.len(), 1);
353    /// assert_eq!(v.as_slice(), &[5]);
354    /// ```
355    pub fn push(&mut self, elem: T) {
356        if self.len == self.cap() {
357            self.buf.grow();
358        }
359
360        unsafe {
361            ptr::write(self.ptr().add(self.len), elem);
362        }
363
364        // This operation will not fail, we will get OOM first.
365        self.len += 1;
366    }
367
368    /// Removes the last element and returns it, or `None` if empty.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use lessvec::LessVec;
374    /// let mut v = LessVec::new();
375    /// v.push(10);
376    /// assert_eq!(v.pop(), Some(10));
377    /// assert_eq!(v.pop(), None);
378    /// ```
379    pub fn pop(&mut self) -> Option<T> {
380        if self.len == 0 {
381            None
382        } else {
383            self.len -= 1;
384            unsafe { Some(ptr::read(self.ptr().add(self.len))) }
385        }
386    }
387
388    /// Inserts an element at `index`, shifting elements to the right.
389    ///
390    /// # Panics
391    ///
392    /// Panics if `index > len`.
393    ///
394    /// # Examples
395    ///
396    /// ```
397    /// use lessvec::LessVec;
398    /// let mut v = LessVec::new();
399    /// v.push(1);
400    /// v.push(3);
401    /// v.insert(1, 2);
402    /// assert_eq!(v.as_slice(), &[1, 2, 3]);
403    /// ```
404    pub fn insert(&mut self, index: usize, elem: T) {
405        assert!(index <= self.len, "index out of bounds");
406        if self.len == self.cap() {
407            self.buf.grow();
408        }
409
410        unsafe {
411            ptr::copy(
412                self.ptr().add(index),
413                self.ptr().add(index + 1),
414                self.len - index,
415            );
416            ptr::write(self.ptr().add(index), elem);
417        }
418
419        self.len += 1;
420    }
421
422    /// Removes and returns the element at `index`, shifting elements left.
423    ///
424    /// # Panics
425    ///
426    /// Panics if `index >= len`.
427    ///
428    /// # Examples
429    ///
430    /// ```
431    /// use lessvec::LessVec;
432    /// let mut v = LessVec::new();
433    /// v.push(1);
434    /// v.push(2);
435    /// assert_eq!(v.remove(0), 1);
436    /// assert_eq!(v.as_slice(), &[2]);
437    /// ```
438    pub fn remove(&mut self, index: usize) -> T {
439        assert!(index < self.len, "index out of bounds");
440        unsafe {
441            self.len -= 1;
442            let result = ptr::read(self.ptr().add(index));
443            ptr::copy(
444                self.ptr().add(index + 1),
445                self.ptr().add(index),
446                self.len - index,
447            );
448            result
449        }
450    }
451
452    /// Removes all elements and returns an iterator that yields the removed elements.
453    ///
454    /// The vector's length is set to zero immediately; elements are yielded by the returned iterator.
455    ///
456    /// # Examples
457    ///
458    /// ```
459    /// use lessvec::LessVec;
460    /// let mut v = LessVec::new();
461    /// v.push(10);
462    /// v.push(20);
463    /// let drained: Vec<_> = v.drain().collect();
464    /// assert_eq!(drained, vec![10, 20]);
465    /// assert!(v.is_empty());
466    /// ```
467    pub fn drain(&'_ mut self) -> Drain<'_, T> {
468        let iter = unsafe { RawValIter::new(self) };
469
470        self.len = 0;
471
472        Drain {
473            iter,
474            vec: PhantomData,
475        }
476    }
477}
478
479impl<T> Drop for LessVec<T> {
480    fn drop(&mut self) {
481        if self.len != 0 {
482            // deallocation is handled by RawVec
483            while self.pop().is_some() {}
484        }
485    }
486}
487
488impl<T> Deref for LessVec<T> {
489    type Target = [T];
490    fn deref(&self) -> &[T] {
491        unsafe { std::slice::from_raw_parts(self.ptr(), self.len) }
492    }
493}
494
495impl<T> DerefMut for LessVec<T> {
496    fn deref_mut(&mut self) -> &mut [T] {
497        unsafe { std::slice::from_raw_parts_mut(self.ptr(), self.len) }
498    }
499}
500
501struct RawValIter<T> {
502    start: *const T,
503    end: *const T,
504}
505
506impl<T> RawValIter<T> {
507    // unsafe construct because it has no associated lifetimes. This is
508    // necessary to store RawValIter as in the same struct as its actual
509    // allocation. OK to use since it's a private implementation detail.
510    unsafe fn new(slice: &[T]) -> Self {
511        RawValIter {
512            start: slice.as_ptr(),
513            end: if mem::size_of::<T>() == 0 {
514                ((slice.as_ptr() as usize) + slice.len()) as *const _
515            } else if slice.is_empty() {
516                slice.as_ptr()
517            } else {
518                unsafe { slice.as_ptr().add(slice.len()) }
519            },
520        }
521    }
522}
523
524impl<T> Iterator for RawValIter<T> {
525    type Item = T;
526    fn next(&mut self) -> Option<T> {
527        if self.start == self.end {
528            None
529        } else {
530            unsafe {
531                if mem::size_of::<T>() == 0 {
532                    self.start = (self.start as usize + 1) as *const _;
533                    Some(ptr::read(NonNull::<T>::dangling().as_ptr()))
534                } else {
535                    let old_ptr = self.start;
536                    self.start = self.start.offset(1);
537                    Some(ptr::read(old_ptr))
538                }
539            }
540        }
541    }
542
543    fn size_hint(&self) -> (usize, Option<usize>) {
544        let elem_size = mem::size_of::<T>();
545        let len =
546            (self.end as usize - self.start as usize) / if elem_size == 0 { 1 } else { elem_size };
547
548        (len, Some(len))
549    }
550}
551
552impl<T> DoubleEndedIterator for RawValIter<T> {
553    fn next_back(&mut self) -> Option<T> {
554        if self.start == self.end {
555            None
556        } else {
557            unsafe {
558                if mem::size_of::<T>() == 0 {
559                    self.end = (self.end as usize - 1) as *const _;
560                    Some(ptr::read(NonNull::<T>::dangling().as_ptr()))
561                } else {
562                    self.end = self.end.offset(-1);
563                    Some(ptr::read(self.end))
564                }
565            }
566        }
567    }
568}
569
570/// Iterator that yields values by value when consuming a `LessVec`.
571///
572/// # Examples
573///
574/// ```
575/// use lessvec::LessVec;
576/// let mut v = LessVec::new();
577/// v.push(1);
578/// v.push(2);
579/// let out: Vec<_> = v.into_iter().collect();
580/// assert_eq!(out, vec![1, 2]);
581/// ```
582pub struct IntoIter<T> {
583    _buf: RawVec<T>,
584    iter: RawValIter<T>,
585}
586
587impl<T> Iterator for IntoIter<T> {
588    type Item = T;
589    fn next(&mut self) -> Option<T> {
590        self.iter.next()
591    }
592
593    fn size_hint(&self) -> (usize, Option<usize>) {
594        self.iter.size_hint()
595    }
596}
597
598impl<T> DoubleEndedIterator for IntoIter<T> {
599    fn next_back(&mut self) -> Option<T> {
600        self.iter.next_back()
601    }
602}
603
604impl<T> Drop for IntoIter<T> {
605    fn drop(&mut self) {
606        for _ in &mut *self {}
607    }
608}
609
610impl<T> IntoIterator for LessVec<T> {
611    type Item = T;
612    type IntoIter = IntoIter<T>;
613    fn into_iter(self) -> IntoIter<T> {
614        unsafe {
615            let iter = RawValIter::new(&self);
616
617            let buf = ptr::read(&self.buf);
618            mem::forget(self);
619
620            IntoIter { _buf: buf, iter }
621        }
622    }
623}
624
625/// An iterator produced by `LessVec::drain`.
626///
627/// Iterates over and yields the drained elements by value.
628///
629/// # Examples
630///
631/// ```
632/// use lessvec::LessVec;
633/// let mut v = LessVec::new();
634/// v.push(1);
635/// v.push(2);
636/// let drained: Vec<_> = v.drain().collect();
637/// assert_eq!(drained, vec![1, 2]);
638/// ```
639pub struct Drain<'a, T: 'a> {
640    vec: PhantomData<&'a mut LessVec<T>>,
641    iter: RawValIter<T>,
642}
643
644impl<'a, T> Iterator for Drain<'a, T> {
645    type Item = T;
646    fn next(&mut self) -> Option<T> {
647        self.iter.next()
648    }
649
650    fn size_hint(&self) -> (usize, Option<usize>) {
651        self.iter.size_hint()
652    }
653}
654
655impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
656    fn next_back(&mut self) -> Option<Self::Item> {
657        self.iter.next_back()
658    }
659}
660
661impl<'a, T> Drop for Drain<'a, T> {
662    fn drop(&mut self) {
663        for _ in &mut *self {}
664    }
665}
666
667#[cfg(test)]
668mod tests {
669    use crate::prelude::*;
670
671    #[test]
672    fn push_pop_roundtrip() {
673        let mut v = LessVec::new();
674        v.push(1);
675        v.push(2);
676        v.push(3);
677
678        assert_eq!(v.pop(), Some(3));
679        assert_eq!(v.pop(), Some(2));
680        assert_eq!(v.pop(), Some(1));
681        assert_eq!(v.pop(), None);
682    }
683
684    #[test]
685    fn insert_remove() {
686        let mut v = LessVec::new();
687        v.push(1);
688        v.push(3);
689        v.insert(1, 2);
690
691        assert_eq!(&*v, &[1, 2, 3]);
692        assert_eq!(v.remove(1), 2);
693        assert_eq!(&*v, &[1, 3]);
694    }
695
696    #[test]
697    fn drain_consumes_elements() {
698        let mut v = LessVec::new();
699        v.push(10);
700        v.push(20);
701        v.push(30);
702
703        let drained: Vec<_> = v.drain().collect();
704        assert_eq!(drained, vec![10, 20, 30]);
705        assert_eq!(&*v, &[]);
706    }
707
708    #[test]
709    fn into_iter_works() {
710        let mut v = LessVec::new();
711        v.push(1);
712        v.push(2);
713        v.push(3);
714
715        let collected: Vec<_> = v.into_iter().collect();
716        assert_eq!(collected, vec![1, 2, 3]);
717    }
718
719    #[test]
720    fn reserve_and_capacity() {
721        let mut v: LessVec<i32> = LessVec::new();
722        v.reserve(5);
723        assert!(v.capacity() >= 5);
724        v.reserve_exact(10);
725        assert!(v.capacity() >= 10);
726    }
727
728    #[test]
729    fn clear_works() {
730        let mut v = LessVec::new();
731        v.push(1);
732        v.clear();
733        assert!(v.is_empty());
734    }
735
736    #[test]
737    fn as_slice_and_mut() {
738        let mut v = LessVec::new();
739        v.push(1);
740        assert_eq!(v.as_slice(), &[1]);
741        v.as_mut_slice()[0] = 2;
742        assert_eq!(v.as_slice(), &[2]);
743    }
744
745    #[test]
746    fn macro_basic() {
747        let v = lessvec![1, 2, 3];
748        assert_eq!(&*v, &[1, 2, 3]);
749    }
750
751    #[test]
752    fn macro_empty() {
753        let v: LessVec<i32> = lessvec![];
754        assert_eq!(v.len(), 0);
755    }
756
757    #[test]
758    fn macro_repeat() {
759        let v = lessvec![5; 3];
760        assert_eq!(&*v, &[5, 5, 5]);
761    }
762}