use core::iter;
use core::num::{self, NonZero};
use core::ops::RangeInclusive;
use crate::patterns::{
factory_is_self, impl_iterator_for_newtype, impl_newtype_generic, impl_via_array,
};
use crate::Exhaust;
macro_rules! impl_nonzero_signed {
($t:ty) => {
impl Exhaust for NonZero<$t> {
type Iter = ExhaustNonZeroSigned<$t, NonZero<$t>>;
fn exhaust_factories() -> Self::Iter {
ExhaustNonZeroSigned::<$t, NonZero<$t>>(
<$t>::exhaust_factories().filter_map(NonZero::new),
)
}
factory_is_self!();
}
};
}
macro_rules! impl_nonzero_unsigned {
($t:ty) => {
impl Exhaust for NonZero<$t> {
type Iter = ExhaustNonZeroUnsigned<$t>;
fn exhaust_factories() -> Self::Iter {
const { ExhaustNonZeroUnsigned(1..=<$t>::MAX) }
}
factory_is_self!();
}
const _: () = {
fn nonzero_or_panic(value: $t) -> NonZero<$t> {
match NonZero::try_from(value) {
Ok(nz) => nz,
Err(_) => unreachable!(),
}
}
impl_iterator_for_newtype!([] for ExhaustNonZeroUnsigned<$t> {
type Item = NonZero<$t>;
fn mapper = nonzero_or_panic;
double_ended_where [];
});
impl iter::FusedIterator for ExhaustNonZeroUnsigned<$t> {}
impl iter::ExactSizeIterator for ExhaustNonZeroUnsigned<$t> {}
};
};
}
impl_nonzero_signed!(i8);
impl_nonzero_signed!(i16);
impl_nonzero_signed!(i32);
impl_nonzero_unsigned!(u8);
impl_nonzero_unsigned!(u16);
impl_nonzero_unsigned!(u32);
#[derive(Clone, Debug)]
#[doc(hidden)]
#[allow(clippy::type_complexity)]
pub struct ExhaustNonZeroSigned<T: Exhaust, N>(
iter::FilterMap<<T as Exhaust>::Iter, fn(<T as Exhaust>::Factory) -> Option<N>>,
);
impl<T: Exhaust, N> Iterator for ExhaustNonZeroSigned<T, N> {
type Item = N;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (mut lower, upper) = self.0.size_hint();
if let Some(upper) = upper {
lower = upper.saturating_sub(1);
}
(lower, upper)
}
}
impl<T: Exhaust, N> iter::FusedIterator for ExhaustNonZeroSigned<T, N> {}
#[derive(Clone, Debug)]
#[doc(hidden)]
pub struct ExhaustNonZeroUnsigned<T>(RangeInclusive<T>);
impl_via_array!(
num::FpCategory,
[
num::FpCategory::Nan,
num::FpCategory::Infinite,
num::FpCategory::Zero,
num::FpCategory::Subnormal,
num::FpCategory::Normal,
]
);
impl_newtype_generic!(T: [], num::Saturating<T>, num::Saturating);
impl_newtype_generic!(T: [], num::Wrapping<T>, num::Wrapping);