Crate mitsein

Source
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 Cargo features 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_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 (depending on which Cargo features 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. Iterator1 types can be fallibly constructed from Iterator types and support many infallible constructions from non-empty collections and views as well as combinators that cannot reduce cardinality to zero (e.g., map).

Supporting traits are re-exported in the prelude module and provide methods for bridging between non-empty Iterator1 types and Iterator types.

use mitsein::iter1;
use mitsein::prelude::*;

let xs = iter1::head_and_tail(0i32, [1, 2]);
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]);

Non-empty collections and views naturally support iteration, collection, etc. via Iterator1. 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 through a Segment. 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 Segmentation trait.

§Integrations and Cargo Features

Mitsein supports no_std environments and provides features 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 Cargo features and integrations.

FeatureDefaultPrimary DependencyDescription
allocNoallocNon-empty collections that allocate, like Vec1.
arbitraryNoarbitraryConstruction of arbitrary non-empty collections.
arrayvecNoarrayvecNon-empty implementations of arrayvec types.
indexmapNoindexmapNon-empty implementations of indexmap types.
itertoolsNoitertoolsCombinators from itertools for Iterator1.
rayonNorayonParallel operations for non-empty types.
serdeNoserdeDe/serialization of non-empty collections with serde.
smallvecNosmallvecNon-empty implementations of smallvec types.
stdYesstdIntegrations with std::io.

Modules§

array1
Non-empty arrays.
array_vec1arrayvec
A non-empty ArrayVec.
borrow1alloc
Non-empty copy-on-write types.
boxed1alloc
Non-empty boxed collections.
btree_map1alloc
A non-empty BTreeMap.
btree_set1alloc
A non-empty BTreeSet.
cmp
Comparison and ordering extensions.
index_map1indexmap
A non-empty IndexMap.
index_set1indexmap
A non-empty IndexSet.
iter1
Non-empty iterators.
prelude
Re-exports of recommended APIs and extension traits for glob imports.
slice1
A non-empty slice.
small_vec1smallvec
A non-empty SmallVec.
str1
A non-empty str.
string1alloc
A non-empty String.
sync1alloc and target_has_atomic="ptr"
Non-empty synchronized collections.
vec1alloc
A non-empty Vec.
vec_deque1alloc
A non-empty VecDeque.

Macros§

slice1
vec1alloc

Structs§

NonEmpty
Segmentarrayvec or alloc
TakeOrarrayvec or alloc

Enums§

Cardinality

Traits§

Segmentationarrayvec or alloc
SegmentedByarrayvec or alloc
SegmentedOverarrayvec or alloc