Trait exhaust::Exhaust

source ·
pub trait Exhaust: Clone {
    type Iter: Iterator<Item = Self> + Clone;

    // Required method
    fn exhaust() -> Self::Iter;
}
Expand description

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 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"),
);

Required Associated Types§

source

type Iter: Iterator<Item = Self> + 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).

Required Methods§

source

fn exhaust() -> Self::Iter

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.

Implementations on Foreign Types§

source§

impl<T: Exhaust, const N: usize> Exhaust for [T; N]

§

type Iter = ExhaustArray<T, N>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for NonZeroI32

source§

impl<H> Exhaust for BuildHasherDefault<H>

source§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Exhaust for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust, T6: Exhaust, T7: Exhaust, T8: Exhaust, T9: Exhaust, T10: Exhaust,

§

type Iter = ExhaustTuple11<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>

source§

fn exhaust() -> Self::Iter

source§

impl<T: Exhaust + AsRef<[u8]>> Exhaust for Cursor<T>

source§

fn exhaust() -> Self::Iter

Returns each combination of a buffer state and a cursor position, except for those where the position is beyond the end of the buffer.

§

type Iter = FlatZipMap<<T as Exhaust>::Iter, RangeInclusive<u64>, Cursor<T>>

source§

impl Exhaust for bool

§

type Iter = IntoIter<bool, { $array.len() }>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for i16

source§

impl Exhaust for PhantomPinned

source§

impl<T: Exhaust> Exhaust for Poll<T>

§

type Iter = Map<<Option<T> as Exhaust>::Iter, fn(_: Option<T>) -> Poll<T>>

source§

fn exhaust() -> Self::Iter

source§

impl<T0, T1, T2, T3, T4, T5> Exhaust for (T0, T1, T2, T3, T4, T5)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust,

§

type Iter = ExhaustTuple6<T0, T1, T2, T3, T4, T5>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for NonZeroI16

source§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Exhaust for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust, T6: Exhaust, T7: Exhaust, T8: Exhaust, T9: Exhaust, T10: Exhaust, T11: Exhaust,

§

type Iter = ExhaustTuple12<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>

source§

fn exhaust() -> Self::Iter

source§

impl<K: Exhaust + Ord, V: Exhaust> Exhaust for BTreeMap<K, V>

§

type Iter = ExhaustBTreeMap<K, V>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for Infallible

source§

impl<T0, T1, T2, T3, T4> Exhaust for (T0, T1, T2, T3, T4)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust,

§

type Iter = ExhaustTuple5<T0, T1, T2, T3, T4>

source§

fn exhaust() -> Self::Iter

source§

impl<T0, T1, T2> Exhaust for (T0, T1, T2)where T0: Exhaust, T1: Exhaust, T2: Exhaust,

§

type Iter = ExhaustTuple3<T0, T1, T2>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for ()

§

type Iter = Once<()>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Pin<Box<T>>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Pin<Box<T, Global>>>

source§

fn exhaust() -> Self::Iter

source§

impl<'a, T: Exhaust> Exhaust for Cow<'a, T>

source§

fn exhaust() -> Self::Iter

Note that this implementation necessarily ignores the borrowed versus owned distinction; every value returned will be a Cow::Owned, not a Cow::Borrowed. This agrees with the PartialEq implementation for Cow, which considers owned and borrowed to be equal.

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Cow<'a, T>>

source§

impl<T> Exhaust for (T,)where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> (T,)>

source§

fn exhaust() -> Self::Iter

source§

impl<T: ?Sized> Exhaust for PhantomData<T>

§

type Iter = Once<PhantomData<T>>

source§

fn exhaust() -> Self::Iter

source§

impl<T, S> Exhaust for HashSet<T, S>where T: Exhaust + Eq + Hash, S: Clone + Default + BuildHasher,

§

type Iter = ExhaustHashSet<T, S>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for char

source§

impl<T0, T1, T2, T3, T4, T5, T6, T7> Exhaust for (T0, T1, T2, T3, T4, T5, T6, T7)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust, T6: Exhaust, T7: Exhaust,

§

type Iter = ExhaustTuple8<T0, T1, T2, T3, T4, T5, T6, T7>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for f32

Note: The floats produced include many NaNs (all unequal in representation).

§

type Iter = Map<<u32 as Exhaust>::Iter, fn(_: u32) -> f32>

source§

fn exhaust() -> Self::Iter

source§

impl<K, V, S> Exhaust for HashMap<K, V, S>where K: Exhaust + Eq + Hash, V: Exhaust, S: Clone + Default + BuildHasher,

source§

fn exhaust() -> Self::Iter

Caution: The order in which this iterator produces elements is currently nondeterministic if the hasher S is. (This might be improved in the future.)

§

type Iter = ExhaustHashMap<K, V, S>

source§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Exhaust for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust, T6: Exhaust, T7: Exhaust, T8: Exhaust, T9: Exhaust,

§

type Iter = ExhaustTuple10<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>

source§

fn exhaust() -> Self::Iter

source§

impl<T: Exhaust> Exhaust for Option<T>

§

type Iter = Chain<Once<Option<T>>, Map<<T as Exhaust>::Iter, fn(_: T) -> Option<T>>>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for i32

source§

impl Exhaust for Ordering

§

type Iter = IntoIter<Ordering, { $array.len() }>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Arc<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Arc<T>>

source§

fn exhaust() -> Self::Iter

source§

impl<T: Exhaust, E: Exhaust> Exhaust for Result<T, E>

§

type Iter = ExhaustResult<T, E>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for NonZeroU16

source§

impl<T> Exhaust for RefCell<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> RefCell<T>>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for u8

source§

impl<T0, T1, T2, T3> Exhaust for (T0, T1, T2, T3)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust,

§

type Iter = ExhaustTuple4<T0, T1, T2, T3>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for u16

source§

impl<T0, T1, T2, T3, T4, T5, T6> Exhaust for (T0, T1, T2, T3, T4, T5, T6)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust, T6: Exhaust,

§

type Iter = ExhaustTuple7<T0, T1, T2, T3, T4, T5, T6>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Pin<Arc<T>>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Pin<Arc<T>>>

source§

fn exhaust() -> Self::Iter

source§

impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Exhaust for (T0, T1, T2, T3, T4, T5, T6, T7, T8)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust, T5: Exhaust, T6: Exhaust, T7: Exhaust, T8: Exhaust,

§

type Iter = ExhaustTuple9<T0, T1, T2, T3, T4, T5, T6, T7, T8>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Pending<T>

§

type Iter = Once<Pending<T>>

source§

fn exhaust() -> Self::Iter

source§

impl<T0, T1> Exhaust for (T0, T1)where T0: Exhaust, T1: Exhaust,

§

type Iter = ExhaustTuple2<T0, T1>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for u32

source§

impl<T> Exhaust for Reverse<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Reverse<T>>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for Sink

§

type Iter = Once<Sink>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for NonZeroU8

source§

impl<T> Exhaust for Rc<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Rc<T>>

source§

fn exhaust() -> Self::Iter

source§

impl<T: Exhaust + Ord> Exhaust for BTreeSet<T>

§

type Iter = ExhaustBTreeSet<T>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for FpCategory

§

type Iter = IntoIter<FpCategory, { $array.len() }>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Cell<T>where T: Copy + Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Cell<T>>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Ready<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Ready<T>>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for NonZeroI8

source§

impl Exhaust for Empty

§

type Iter = Once<Empty>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Box<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Box<T, Global>>

source§

fn exhaust() -> Self::Iter

source§

impl<T> Exhaust for Wrapping<T>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Wrapping<T>>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for i8

source§

impl<T> Exhaust for Pin<Rc<T>>where T: Exhaust,

§

type Iter = Map<<T as Exhaust>::Iter, fn(_: T) -> Pin<Rc<T>>>

source§

fn exhaust() -> Self::Iter

source§

impl Exhaust for NonZeroU32

Implementors§