nonempty_collections/lib.rs
1#![allow(rustdoc::redundant_explicit_links)] // the explicit links are needed for cargo rdme
2
3//! Non-empty variants of the standard collections.
4//!
5//! Non-emptiness can be a powerful guarantee. If your main use of `Vec` is as
6//! an `Iterator`, then you may not need to distinguish on emptiness. But there
7//! are indeed times when the `Vec` you receive as a function argument needs to
8//! be non-empty or your function can't proceed. Similarly, there are times when
9//! the `Vec` you return to a calling user needs to promise it actually contains
10//! something.
11//!
12//! With `NEVec`, you're freed from the boilerplate of constantly needing to
13//! check `is_empty()` or pattern matching before proceeding, or erroring if you
14//! can't. So overall, code, type signatures, and logic become cleaner.
15//!
16//! Consider that unlike `Vec`, [`NEVec::first()`] and [`NEVec::last()`] don't
17//! return in `Option`; they always succeed.
18//!
19//! Alongside [`NEVec`](crate::vector::NEVec) are its cousins:
20//!
21//! - [`NESlice`](crate::slice::NESlice)
22//! - [`NESet`](crate::set::NESet)
23//! - [`NEMap`](crate::map::NEMap)
24//! - [`NEBTreeSet`](crate::btree_set::NEBTreeSet)
25//! - [`NEBTreeMap`](crate::btree_map::NEBTreeMap)
26//!
27//! which are all guaranteed to contain at least one item.
28//!
29//! # Examples
30//!
31//! The simplest way to construct these non-empty collections is via their
32//! macros: [`nev!`], [`nes!`], [`nem!`], [`nebts!`] and [`nebtm!`]:
33//!
34//! ```
35//! use nonempty_collections::*;
36//!
37//! let v: NEVec<u32> = nev![1, 2, 3];
38//! let s: NESet<u32> = nes![1, 2, 2, 3]; // 1 2 3
39//! let m: NEMap<&str, bool> = nem!["a" => true, "b" => false];
40//! assert_eq!(&1, v.first());
41//! assert_eq!(3, s.len().get());
42//! assert!(m.get("a").unwrap());
43//! ```
44//!
45//! Unlike the familiar `vec!` macro, `nev!` and friends require at least one
46//! element:
47//!
48//! ```
49//! use nonempty_collections::nev;
50//!
51//! let v = nev![1];
52//! ```
53//!
54//! A value must be provided:
55//!
56//! ```compile_fail
57//! let v = nev![]; // Doesn't compile!
58//! ```
59//!
60//! Like `Vec`, you can also construct a [`NEVec`](crate::vector::NEVec) the old
61//! fashioned way with [`NEVec::new()`] or its constructor:
62//!
63//! ```
64//! use nonempty_collections::NEVec;
65//!
66//! let mut l = NEVec::try_from_vec(vec![42, 36, 58]).unwrap();
67//! assert_eq!(&42, l.first());
68//!
69//! l.push(9001);
70//! assert_eq!(l.last(), &9001);
71//! ```
72//!
73//! And if necessary, you're free to convert to and from `Vec`:
74//!
75//! ```
76//! use nonempty_collections::nev;
77//! use nonempty_collections::NEVec;
78//!
79//! let l: NEVec<u32> = nev![42, 36, 58, 9001];
80//! let v: Vec<u32> = l.into();
81//! assert_eq!(v, vec![42, 36, 58, 9001]);
82//!
83//! let u: Option<NEVec<u32>> = NEVec::try_from_vec(v);
84//! assert_eq!(Some(nev![42, 36, 58, 9001]), u);
85//! ```
86//!
87//! # Iterators
88//!
89//! This library extends the notion of non-emptiness to iterators, and provides
90//! the [`NonEmptyIterator`](crate::iter::NonEmptyIterator) trait. This has some
91//! interesting consequences:
92//!
93//! - Functions like `map` preserve non-emptiness.
94//! - Functions like `max` always have a result.
95//! - A non-empty iterator chain can be `collect`ed back into a non-empty
96//! structure.
97//! - You can chain many operations together without having to double-check for
98//! emptiness.
99//!
100//! ```
101//! use nonempty_collections::*;
102//!
103//! let v: NEVec<_> = nev![1, 2, 3].into_nonempty_iter().map(|n| n + 1).collect();
104//! assert_eq!(&2, v.first());
105//! ```
106//!
107//! Consider also [`IntoIteratorExt::try_into_nonempty_iter`] for converting any
108//! given [`Iterator`] and [`IntoIterator`] into a non-empty one, if it contains
109//! at least one item.
110//!
111//! # Arrays
112//!
113//! Since fixed-size arrays are by definition already not empty, they aren't
114//! given a special wrapper type like [`NEVec`](crate::vector::NEVec). Instead,
115//! we enable them to be easily iterated over in a compatible way:
116//!
117//! ```
118//! use nonempty_collections::*;
119//!
120//! let a: [u32; 4] = [1, 2, 3, 4];
121//! let v: NEVec<_> = a.into_nonempty_iter().map(|n| n + 1).collect();
122//! assert_eq!(nev![2, 3, 4, 5], v);
123//! ```
124//! See [`NonEmptyArrayExt`](crate::array::NonEmptyArrayExt) for more
125//! conversions.
126//!
127//! # Caveats
128//!
129//! Since `NEVec` and friends must have a least one element, it is not
130//! possible to implement the [`FromIterator`] trait for them. We can't
131//! know, in general, if any given standard-library [`Iterator`] actually
132//! contains something.
133//!
134//! # Features
135//!
136//! * `serde`: `serde` support.
137//! * `indexmap`: adds [`NEIndexMap`](crate::index_map::NEIndexMap) a non-empty [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/).
138//! * `itertools`: adds [`NonEmptyItertools`](crate::itertools::NonEmptyItertools) a non-empty variant of [`itertools`](https://docs.rs/itertools/latest/itertools/).
139//! * `either`: adds [`NEEither`](crate::either::NEEither) a non-empty variant of `Either` from the [`either` crate](https://docs.rs/either/latest/either/).
140//! * `rand`: adds `NEVec` support for `SliceRandom`.
141
142pub mod array;
143pub mod btree_map;
144pub mod btree_set;
145pub mod iter;
146pub mod map;
147pub mod set;
148pub mod slice;
149pub mod vector;
150
151#[cfg(feature = "either")]
152pub mod either;
153#[cfg(feature = "indexmap")]
154pub mod index_map;
155#[cfg(feature = "indexmap")]
156pub mod index_set;
157#[cfg(feature = "itertools")]
158pub mod itertools;
159
160pub use array::ArrayNonEmptyIterator;
161pub use array::NonEmptyArrayExt;
162pub use btree_map::NEBTreeMap;
163pub use btree_set::NEBTreeSet;
164#[cfg(feature = "either")]
165pub use either::NEEither;
166#[cfg(feature = "indexmap")]
167pub use index_map::NEIndexMap;
168#[cfg(feature = "indexmap")]
169pub use index_set::NEIndexSet;
170pub use iter::FromNonEmptyIterator;
171pub use iter::IntoIteratorExt;
172pub use iter::IntoNonEmptyIterator;
173pub use iter::NonEmptyIterator;
174#[cfg(feature = "itertools")]
175pub use itertools::NonEmptyItertools;
176pub use map::NEMap;
177pub use set::NESet;
178pub use slice::NESlice;
179pub use vector::NEVec;
180
181/// Errors typically involving type conversions.
182#[derive(Debug, Clone, Copy)]
183pub enum Error {
184 /// There was nothing to decode.
185 Empty,
186}
187
188impl std::fmt::Display for Error {
189 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190 match self {
191 Error::Empty => write!(f, "Given collection was empty"),
192 }
193 }
194}
195
196/// A type that can be instantiated via a single item - the kindred spirit to
197/// [`Default`].
198pub trait Singleton {
199 type Item;
200
201 fn singleton(item: Self::Item) -> Self;
202}