1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
#![no_std]
//! This crate provides the [`Exhaust`] trait and derive macro, which allow iterating over
//! all values of a given type.
#![forbid(rust_2018_idioms)]
#![forbid(unsafe_code)]
#![warn(unreachable_pub)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![warn(clippy::cast_lossless)]
#![warn(clippy::exhaustive_enums)]
#![warn(clippy::exhaustive_structs)]
#![warn(clippy::pedantic)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub use exhaust_macros::Exhaust;
pub(crate) mod patterns;
pub mod impls;
/// Reexport for compatibility with v0.1.0;
/// new code should use [`impls::ExhaustArray`](ExhaustArray).
pub use impls::ExhaustArray;
mod convenience;
pub use convenience::*;
pub mod iteration;
/// Types that can be exhaustively iterated. That is, an iterator is available which
/// produces every possible value of this type.
///
/// Implementors must also implement [`Clone`], because it is useful for the purpose of
/// implementing [`Exhaust`] on types containing this type. This should never be a
/// significant restriction since a type implementing [`Exhaust`] implies that every
/// instance can be derived from pure data (“the Nth element of `T::exhaust()`”).
///
/// # Examples
///
/// Using [the derive macro](macro@Exhaust) to implement the trait:
///
/// ```
/// use exhaust::Exhaust;
///
/// #[derive(Clone, PartialEq, Debug, Exhaust)]
/// struct Foo {
/// a: bool,
/// b: Bar,
/// }
///
/// #[derive(Clone, PartialEq, Debug, Exhaust)]
/// enum Bar {
/// One,
/// Two(bool),
/// }
///
/// assert_eq!(
/// Foo::exhaust().collect::<Vec<Foo>>(),
/// vec![
/// Foo { a: false, b: Bar::One },
/// Foo { a: false, b: Bar::Two(false) },
/// Foo { a: false, b: Bar::Two(true) },
/// Foo { a: true, b: Bar::One },
/// Foo { a: true, b: Bar::Two(false) },
/// Foo { a: true, b: Bar::Two(true) },
/// ],
/// );
/// ```
///
/// Writing a manual implementation of `Exhaust`:
///
/// ```
/// use exhaust::Exhaust;
///
/// #[derive(Clone)]
/// struct AsciiLetter(char);
///
/// impl Exhaust for AsciiLetter {
/// type Iter = ExhaustAsciiLetter;
/// fn exhaust() -> Self::Iter {
/// ExhaustAsciiLetter { next: 'A' }
/// }
/// }
///
/// #[derive(Clone)]
/// struct ExhaustAsciiLetter {
/// next: char
/// }
///
/// impl Iterator for ExhaustAsciiLetter {
/// type Item = AsciiLetter;
///
/// fn next(&mut self) -> Option<Self::Item> {
/// match self.next {
/// 'A'..='Y' | 'a'..='z' => {
/// let item = self.next;
/// self.next = char::from_u32(self.next as u32 + 1).unwrap();
/// Some(AsciiLetter(item))
/// }
/// 'Z' => {
/// self.next = 'a';
/// Some(AsciiLetter('Z'))
/// }
/// '{' => None, // ('z' + 1)
/// _ => unreachable!(),
/// }
/// }
/// }
///
/// assert_eq!(
/// AsciiLetter::exhaust().map(|l| l.0).collect::<String>(),
/// String::from("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
/// );
/// ```
pub trait Exhaust: Clone {
/// Type of iterator returned by [`Self::exhaust()`].
///
/// Note: While it is necessary for this type to be exposed, an implementation of
/// [`Exhaust`] changing this to another type should not be considered a breaking
/// change, as long as it still has the same iterator properties (e.g.
/// [`ExactSizeIterator`]).
type Iter: Iterator<Item = Self> + Clone;
/// Returns an iterator over all values of this type.
///
/// Implementations should have the following properties:
///
/// * For any two items `a, b` produced by the iterator, `a != b`.
/// * For every value `a` of type `Self`, there is some element `b` of `Self::exhaust()`
/// for which `a == b`, unless it is the case that `a != a`.
/// * If there is any value `a` of type `Self` for which `a != a`, then [`Exhaust`]
/// must produce one or more such values.
/// * `exhaust()` does not panic, nor does the iterator it returns.
/// * Purity/determinism: every call to `Self::exhaust()`, or [`Clone::clone()`] of a returned
/// iterator, should produce the same sequence of items.
/// * The iterator has a finite length, that is feasible to actually reach.
///
/// [`Exhaust`] is not an `unsafe trait`, and as such, no soundness property should rest
/// on implementations having any of the above properties unless the particular implementation
/// guarantees them.
///
/// The following further properties are recommended when feasible:
///
/// * If `Self: Ord`, then the items are sorted in ascending order.
fn exhaust() -> Self::Iter;
}