14 releases (7 breaking)

new 0.8.1 Dec 6, 2022
0.8.0 Jun 30, 2022
0.7.0 Jun 22, 2021
0.6.0 Oct 23, 2020
0.1.5 Nov 25, 2019

#92 in Rust patterns

Download history 7421/week @ 2022-08-17 8193/week @ 2022-08-24 12186/week @ 2022-08-31 8818/week @ 2022-09-07 10391/week @ 2022-09-14 9347/week @ 2022-09-21 8510/week @ 2022-09-28 9774/week @ 2022-10-05 7855/week @ 2022-10-12 9820/week @ 2022-10-19 9220/week @ 2022-10-26 12760/week @ 2022-11-02 10978/week @ 2022-11-09 13663/week @ 2022-11-16 10387/week @ 2022-11-23 11214/week @ 2022-11-30

48,627 downloads per month
Used in 33 crates (17 directly)

MIT license

37KB
547 lines

Correct by Construction Non-Empty List

This package exposes a type NonEmpty<T> with a data representation that guarantees non-emptiness statically:

struct NonEmpty<T>(T, Vec<T>)

The library is meant to have an interface similar to std::vec::Vec:

use nonempty::NonEmpty;

let mut l = NonEmpty::new(42);

assert_eq!(l.first(), &42);

l.push(36);
l.push(58);

let v: Vec<i32> = l.into();
assert_eq!(v, vec![42, 36, 58]);

lib.rs:

A Non-empty growable vector.

Non-emptiness can be a powerful guarantee. If your main use of Vec is as an Iterator, then you may not need to distinguish on emptiness. But there are indeed times when the Vec you receive as as function argument needs to be non-empty or your function can't proceed. Similarly, there are times when the Vec you return to a calling user needs to promise it actually contains something.

With NonEmpty, you're freed from the boilerplate of constantly needing to check is_empty() or pattern matching before proceeding, or erroring if you can't. So overall, code, type signatures, and logic become cleaner.

Consider that unlike Vec, [NonEmpty::first] and [NonEmpty::last] don't return in Option, they always succeed.

Examples

The simplest way to construct a [NonEmpty] is via the [nonempty] macro:

use nonempty::{NonEmpty, nonempty};

let l: NonEmpty<u32> = nonempty![1, 2, 3];
assert_eq!(l.head, 1);

Unlike the familiar vec! macro, nonempty! requires at least one element:

use nonempty::nonempty;

let l = nonempty![1];

// Doesn't compile!
// let l = nonempty![];

Like Vec, you can also construct a [NonEmpty] the old fashioned way with [NonEmpty::new] or its constructor:

use nonempty::NonEmpty;

let mut l = NonEmpty { head: 42, tail: vec![36, 58] };
assert_eq!(l.head, 42);

l.push(9001);
assert_eq!(l.last(), &9001);

And if necessary, you're free to convert to and from Vec:

use nonempty::{NonEmpty, nonempty};

let l: NonEmpty<u32> = nonempty![42, 36, 58, 9001];
let v: Vec<u32> = l.into();
assert_eq!(v, vec![42, 36, 58, 9001]);

let u: Option<NonEmpty<u32>> = NonEmpty::from_vec(v);
assert_eq!(Some(nonempty![42, 36, 58, 9001]), u);

Caveats

Since NonEmpty must have a least one element, it is not possible to implement the FromInterator trait for it. We can't know, in general, if any given Iterator actually contains something.

Features

  • serialize: serde support.

Dependencies

~160KB