Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 89 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,69 @@ impl<T> NonEmpty<T> {
Self::singleton(e)
}

/// Constructs a new `NonEmpty<T>` 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<T>` 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<T>` to `NonEmpty<&T>`.
pub fn as_ref(&self) -> NonEmpty<&T> {
NonEmpty {
Expand Down Expand Up @@ -423,7 +486,7 @@ impl<T> NonEmpty<T> {
/// assert_eq!(l_iter.next(), Some(&58));
/// assert_eq!(l_iter.next(), None);
/// ```
pub fn iter(&self) -> Iter<T> {
pub fn iter(&self) -> Iter<'_, T> {
Iter {
head: Some(&self.head),
tail: &self.tail,
Expand Down Expand Up @@ -1091,6 +1154,7 @@ pub mod serialize {
#[cfg(test)]
mod tests {
use alloc::{string::String, vec::Vec};
use core::num::NonZeroUsize;

use crate::NonEmpty;

Expand All @@ -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]));
Expand Down