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