Expand description
Mitsein provides strongly typed APIs for non-empty collections and views, including (but not limited to) iterators, slices, and containers. Where possible, unnecessary branches are omitted and APIs enforce and reflect the non-empty invariant.
use mitsein::prelude::*;
let mut xs = vec1![0i64, 1, -3];
xs.push(2);
assert_eq!(&0, xs.first());
assert_eq!(6, xs.into_iter1().map(|x| x * 2).map(i64::abs).max());Note in the above example that operations on xs yield non-optional outputs,
because xs is non-empty.
Modules in this crate reflect corresponding modules in core, alloc, and std, though
collection modules are exported at the crate root rather than a collections module. For
example, Vec is exported in alloc::vec::Vec and its non-empty counterpart Vec1 is
exported in mitsein::vec1::Vec1. APIs in this crate are typically named by appending 1 to
the names of their counterparts.
At time of writing, rustdoc ignores input type parameters in the “Methods from
Deref<Target = _>” section. For types that implement Deref<Target = NonEmpty<_>>, the API
documentation may be misleading and list all methods of NonEmpty regardless of its input
type parameter. This is mostly a problem for types that dereference to Slice1, such as
Vec1. See this rustdoc bug.
§Non-Empty Types
Types that represent non-empty collections, containers, or views present APIs that reflect the
non-empty guarantee. The names of these types are formed by appending 1 to the name of their
counterparts. For example, the non-empty Vec type is Vec1.
§Collections
This crate provides the following non-empty collections and supporting APIs (depending on which feature flags are enabled):
Non-empty collections are represented with the NonEmpty type constructor. These types are
exported as type definitions in their respective modules. Similarly to std::prelude, the
prelude module notably re-exports Vec1 and the vec1! macro.
use mitsein::prelude::*;
let mut xs = Vec1::from_head_and_tail(0i64, [1, 2, 3]);
while let Ok(_) = xs.pop_if_many().or_get_only() {}
assert_eq!(xs.as_slice(), &[0]);§Slices
Like collections, non-empty slices are represented with the NonEmpty type constructor and
the Slice1 and Str1 type definitions. These types are unsized and so are accessed via
references just like standard slices. The prelude module re-exports Slice1 and the
slice1! macro.
use mitsein::prelude::*;
fn fold_terminals<T, U, F>(xs: &Slice1<T>, f: F) -> U
where
F: FnOnce(&T, &T) -> U,
{
f(xs.first(), xs.last())
}
let xs = slice1![0i64, 1, 2, 3];
let y = fold_terminals(xs, |first, last| first + last);
assert_eq!(y, 3);See the slice1 and str1 modules.
§Containers
This crate provides the following non-empty containers for slices and strings (depending on which feature flags are enabled):
Each of these type definitions has an accompanying extension trait for operations and
conversions that take advantage of the non-empty guarantee. For example, ArcSlice1Ext
provides APIs for non-empty slices in an Arc. Some collection types like Vec1 support
conversions from and into these containers.
§Iterators
Non-empty iterators are provided by the Iterator1 type constructor and directly support
combinators that never reduce cardinality to zero (e.g., map). Non-empty
collections and views naturally support iteration, collection, etc. via Iterator1.
use mitsein::prelude::*;
let xs = vec1![0i32, 1, 2];
let ys: Vec1<_> = xs.iter1().copied().map(|x| x + 1).collect1();
assert_eq!(ys.as_slice(), &[1, 2, 3]);Supporting traits are re-exported in the prelude module and provide methods for bridging
between non-empty Iterator1 types and maybe-empty Iterator types.
use mitsein::iter1;
use mitsein::prelude::*;
let xs = iter1::head_and_tail(0i32, [1, 2]);
// `Iterator1` does not support `skip`, so `xs` is converted into an `Iterator` and then into a
// different `Iterator1` via `or_non_empty`.
let xs: Vec1<_> = xs.into_iter().skip(3).or_non_empty([3]).collect1();
let ys = Vec::new();
let ys: Vec1<_> = ys.extend_non_empty([0i32]);
assert_eq!(xs.as_slice(), &[3]);
assert_eq!(ys.as_slice(), &[0]);When the rayon feature is enabled, the ParallelIterator1 type implements parallel and
non-empty iterators.
See the iter1 module.
§Arrays
Because primitive arrays must contain initialized items at capacity in safe code, the only
empty array types are [_; 0]. The Array1 trait is implemented for arrays with a non-zero
cardinality and provides conversions and operations that take advantage of the non-empty
guarantee of such arrays.
use mitsein::prelude::*;
let mut xs = [0i64, 1, 2, 3];
let x = xs.as_mut_slice1().first_mut();
*x = 4;
assert_eq!(xs.as_slice(), &[4, 1, 2, 3]);At time of writing, it is not possible to implement Array1 for any and all non-empty array
types, so this trait is only implemented for arrays with one to 64 items.
See the array1 module.
§Segmentation
A Segment is a view over a subset of a collection that can mutate both the items and
topology of its target. This is somewhat similar to a mutable slice, but items can also be
inserted and removed. This crate implements segmentation for both standard and non-empty
collections and is one of the most efficient ways to remove and drain items from non-empty
collections.
use mitsein::prelude::*;
let mut xs = vec1![0i64, 1, 2, 3, 4];
xs.tail().clear(); // Efficiently clears the tail segment of `xs`.
assert_eq!(xs.as_slice(), &[0]);See the segment module.
§Integrations and Feature Flags
Mitsein supports no_std environments and provides feature flags for integrating as needed
with alloc and std. By default, the std feature is enabled for complete support of
the standard library.
The following table summarizes supported feature flags and integrations.
| Feature | Also Enables | Default | Crate | Description |
|---|---|---|---|---|
alloc | No | alloc | Non-empty collections that allocate, like Vec1. | |
arbitrary | std | No | arbitrary | Construction of arbitrary non-empty collections. |
arrayvec | No | arrayvec | Non-empty implementations of arrayvec types. | |
either | No | either | Non-empty iterator implementation for Either. | |
indexmap | alloc | No | indexmap | Non-empty implementations of indexmap types. |
itertools | either | No | itertools | Combinators from itertools for Iterator1. |
rayon | std | No | rayon | Parallel operations for non-empty types. |
schemars | alloc | No | schemars | JSON schema generation for non-empty types. |
serde | No | serde | De/serialization of non-empty collections with serde. | |
smallvec | alloc | No | smallvec | Non-empty implementations of smallvec types. |
std | alloc | Yes | std | Integrations with std::io. |
Modules§
- array1
- Non-empty arrays.
- array_
vec1 arrayvec - A non-empty
ArrayVec. - borrow1
alloc - Non-empty copy-on-write types.
- boxed1
alloc - Non-empty boxed collections.
- btree_
map1 alloc - A non-empty
BTreeMap. - btree_
set1 alloc - A non-empty
BTreeSet. - cmp
- Comparison and ordering extensions.
- index_
map1 indexmap - A non-empty
IndexMap. - index_
set1 indexmap - A non-empty
IndexSet. - iter1
- Non-empty iterators.
- prelude
- Re-exports of recommended APIs and extension traits for glob imports.
- rc1
alloc - Non-empty reference-counted collections.
- segment
arrayvecoralloc - Segmentation of collections.
- slice1
- A non-empty slice.
- small_
vec1 smallvec - A non-empty
SmallVec. - str1
- A non-empty str.
- string1
alloc - A non-empty
String. - sync1
allocandtarget_has_atomic=ptr - Non-empty synchronized collections.
- vec1
alloc - A non-empty
Vec. - vec_
deque1 alloc - A non-empty
VecDeque.
Macros§
Structs§
- Empty
Error - An error in which a non-empty value is expected but an empty value is observed.
- NonEmpty
- A collection or slice type that must contain one or more items (is never empty).
- Take
IfMany arrayvecoralloc
Enums§
- Cardinality
- Non-empty cardinality.