exhaust/impls/
core_num.rs

1use core::iter;
2use core::num::{self, NonZero};
3
4use crate::patterns::{impl_newtype_generic, impl_via_array};
5use crate::Exhaust;
6
7// -------------------------------------------------------------------------------------------------
8
9macro_rules! impl_nonzero {
10    ($t:ty) => {
11        impl Exhaust for NonZero<$t> {
12            type Iter = ExhaustNonZero<$t, NonZero<$t>>;
13
14            fn exhaust_factories() -> Self::Iter {
15                // TODO: This `filter_map()` is tidy and generic, but is probably not the optimal
16                // implementation for unsigned numbers, since if `next()` is not inlined, it'll
17                // need a comparison with zero on each iteration. But I haven’t checked.
18                ExhaustNonZero::<$t, NonZero<$t>>(
19                    <$t>::exhaust_factories().filter_map(NonZero::new),
20                )
21            }
22
23            crate::patterns::factory_is_self!();
24        }
25    };
26}
27
28// Implement `Exhaust` for all `NonZero`-able numbers that are no larger than 32 bits.
29// This should match <https://doc.rust-lang.org/std/num/trait.ZeroablePrimitive.html>
30// (as long as that's the unstable trait backing `NonZero`), except for those that are too large.
31impl_nonzero!(i8);
32impl_nonzero!(i16);
33impl_nonzero!(i32);
34impl_nonzero!(u8);
35impl_nonzero!(u16);
36impl_nonzero!(u32);
37
38/// Iterator implementation for `NonZero::exhaust()`.
39// TODO: This should just be a type_alias_impl_trait for FilterMap when that's stable.
40// Right now, it's just public-in-private so unnameable that way.
41#[derive(Clone, Debug)]
42#[doc(hidden)]
43#[allow(clippy::type_complexity)]
44pub struct ExhaustNonZero<T: Exhaust, N>(
45    iter::FilterMap<<T as Exhaust>::Iter, fn(<T as Exhaust>::Factory) -> Option<N>>,
46);
47
48impl<T: Exhaust, N> Iterator for ExhaustNonZero<T, N> {
49    type Item = N;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        self.0.next()
53    }
54}
55impl<T: Exhaust, N> iter::FusedIterator for ExhaustNonZero<T, N> {}
56
57// -------------------------------------------------------------------------------------------------
58
59impl_via_array!(
60    num::FpCategory,
61    [
62        Self::Nan,
63        Self::Infinite,
64        Self::Zero,
65        Self::Subnormal,
66        Self::Normal,
67    ]
68);
69
70impl_newtype_generic!(T: [], num::Wrapping<T>, num::Wrapping);