diff --git a/src/lib.rs b/src/lib.rs index 07465bb..943381d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -221,6 +221,69 @@ impl NonEmpty { Self::singleton(e) } + /// Constructs a new `NonEmpty` with at least the specified capacity. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is one, the vector will not allocate. + /// + /// It is important to note that although the returned vector has the + /// minimum *capacity* specified, the vector will have a zero *length*. For + /// an explanation of the difference between length and capacity, see + /// *[Capacity and reallocation]*. + /// + /// If it is important to know the exact allocated capacity of a `NonEmpty`, + /// always use the [`capacity`] method after construction. + /// + /// For `NonEmpty` where `T` is a zero-sized type, there will be no allocation + /// and the capacity will always be `usize::MAX`. + /// + /// [Capacity and reallocation]: #capacity-and-reallocation + /// [`capacity`]: Vec::capacity + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// + /// # Errors + /// + /// With return Err if `capacity` is 0. + /// + /// # Examples + /// + /// ``` + /// let mut vec = NonEmpty::new_with_capacity(1, NonZeroUsize::new(10).unwrap()); + /// + /// // The vector contains one item, even though it has capacity for more + /// assert_eq!(vec.len(), 1); + /// assert!(vec.capacity().get() >= 10); + /// + /// // These are all done without reallocating... + /// for i in 0..10 { + /// vec.push(i); + /// } + /// assert_eq!(vec.len(), 11); + /// assert!(vec.capacity().get() >= 11); + /// + /// // ...but this may make the vector reallocate + /// vec.push(11); + /// assert_eq!(vec.len(), 12); + /// assert!(vec.capacity().get() >= 12); + /// + /// // A vector of a zero-sized type will always over-allocate, since no + /// // allocation is necessary + /// let vec_units = NonEmpty::<()>::new_with_capacity((), NonZeroUsize::new(10).unwrap()); + /// assert_eq!(vec_units.capacity(), NonZeroUsize::MAX); + /// ``` + #[inline] + #[must_use] + pub fn new_with_capacity(head: T, capacity: NonZeroUsize) -> Self { + Self { + head, + tail: Vec::with_capacity(capacity.get() - 1), + } + } + /// Converts from `&NonEmpty` to `NonEmpty<&T>`. pub fn as_ref(&self) -> NonEmpty<&T> { NonEmpty { @@ -423,7 +486,7 @@ impl NonEmpty { /// assert_eq!(l_iter.next(), Some(&58)); /// assert_eq!(l_iter.next(), None); /// ``` - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter<'_, T> { Iter { head: Some(&self.head), tail: &self.tail, @@ -1091,6 +1154,7 @@ pub mod serialize { #[cfg(test)] mod tests { use alloc::{string::String, vec::Vec}; + use core::num::NonZeroUsize; use crate::NonEmpty; @@ -1104,6 +1168,30 @@ mod tests { assert_eq!(result, expected); } + #[test] + fn test_new_with_capacity() { + let nz_10 = NonZeroUsize::new(10).unwrap(); + let mut vec = NonEmpty::new_with_capacity(1, nz_10); + + assert_eq!(vec.len(), 1); + assert!(vec.capacity() >= nz_10); + + for i in 0..10 { + vec.push(i); + } + let nz_11 = nz_10.saturating_add(1); + assert_eq!(vec.len(), 11); + assert!(vec.capacity() >= nz_11); + + let nz_12 = nz_11.saturating_add(1); + vec.push(11); + assert_eq!(vec.len(), 12); + assert!(vec.capacity() >= nz_12); + + let vec_units = NonEmpty::<()>::new_with_capacity((), nz_10); + assert_eq!(vec_units.capacity(), NonZeroUsize::MAX); + } + #[test] fn test_into_iter() { let nonempty = NonEmpty::from((0, vec![1, 2, 3]));