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§
sourcetype Iter: Iterator<Item = Self> + Clone
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§
sourcefn exhaust() -> Self::Iter
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 typeSelf
, there is some elementb
ofSelf::exhaust()
for whicha == b
, unless it is the case thata != a
. - If there is any value
a
of typeSelf
for whicha != a
, thenExhaust
must produce one or more such values. exhaust()
does not panic, nor does the iterator it returns.- Purity/determinism: every call to
Self::exhaust()
, orClone::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<H> Exhaust for BuildHasherDefault<H>
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,
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,
source§impl Exhaust for PhantomPinned
impl Exhaust for PhantomPinned
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,
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,
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,
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,
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,
impl<T0, T1, T2, T3, T4> Exhaust for (T0, T1, T2, T3, T4)where T0: Exhaust, T1: Exhaust, T2: Exhaust, T3: Exhaust, T4: Exhaust,
source§impl<'a, T: Exhaust> Exhaust for Cow<'a, T>
impl<'a, T: Exhaust> Exhaust for Cow<'a, T>
source§fn exhaust() -> Self::Iter
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: ?Sized> Exhaust for PhantomData<T>
impl<T: ?Sized> Exhaust for PhantomData<T>
source§impl<T, S> Exhaust for HashSet<T, S>where
T: Exhaust + Eq + Hash,
S: Clone + Default + BuildHasher,
impl<T, S> Exhaust for HashSet<T, S>where T: Exhaust + Eq + Hash, S: Clone + Default + BuildHasher,
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,
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,
source§impl Exhaust for f32
impl Exhaust for f32
Note: The floats produced include many NaN
s (all unequal in representation).