| Crates.io | nunny |
| lib.rs | nunny |
| version | 0.2.2 |
| created_at | 2024-04-24 12:47:31.031186+00 |
| updated_at | 2025-06-23 22:56:07.918091+00 |
| description | the definitive non-empty slice/array/vec library for Rust |
| homepage | https://crates.io/nunny |
| repository | https://github.com/aatifsyed/nunny |
| max_upload_size | |
| id | 1218720 |
| size | 261,730 |
The definitive non-empty slice/array/vec library for Rust.
Nonempty-by-construction API
let mut my_vec = NonEmpty::<Vec<_>>::of("hello"); // construct once
my_vec.push("world"); // continue using your normal APIs
let hello: &str = my_vec.first(); // preserve the guarantee that there is at least one element
#[repr(transparent)] allows advanced usecases and guarantees optimum performance1:
let src = &mut ["hello", "world"];
let ne = NonEmpty::<[_]>::new_mut(src).unwrap();
// ^ uses the same backing memory
let world: &str = ne.last();
Total API coverage.
For every impl of [From], [TryFrom], [PartialEq] and [PartialOrd] in [std]2,
there is a corresponding impl in this library for [Slice], [Array] and [Vec].
This includes more exotic types:
let nun: Box<NonEmpty<[_]>> = vec![0xDEAD, 0xBEEF].into();
let cow: Cow<NonEmpty<[_]>> = (&*nun).into();
let arc: Arc<NonEmpty<[_]>> = cow.into_owned().into();
const-friendly API. Where possible, all methods are const.
const TWO: &NonEmpty<[&str]> = slice!["together", "forever"];
const FIRST: &str = TWO.first();
const ONE: &NonEmpty<[&str]> = NonEmpty::<[_]>::of(&"lonely");
Extensive feature gating supporting:
no-std environments with no allocator.alloc-enabled environments.std-enabled environments.serde and arbitrary.Iterator support:
Specialized [Iterator] methods remove branches to handle empty iterators,
and preserve invariants even when chaining combinators.
let v = vec![1, 2, 3];
let _: Option<&u8> = v.iter().last();
// ^ normally you have to handle the empty case
let _: &u8 = v.iter_ne().last();
// ^ but we know there is at least one element
let _: u8 = v.iter_ne().copied().last();
// ^ using this combinator preserves the invariant
Thoughtful design:
NonZeroUsize] is inserted where appropriate.Deref/DerefMuts
down to a [NonEmpty<Slice<T>>], which in turn deref/muts down to a [T].cmp, borrow, convert
traits.
If there's a missing API that you'd like, please raise an issue!