macro_rules! factory_is_self {
() => {
type Factory = Self;
fn from_factory(factory: Self::Factory) -> Self {
factory
}
};
}
pub(crate) use factory_is_self;
macro_rules! delegate_factory_and_iter {
($delegate:ty) => {
type Iter = <$delegate as $crate::Exhaust>::Iter;
type Factory = <$delegate as $crate::Exhaust>::Factory;
fn exhaust_factories() -> Self::Iter {
<$delegate as $crate::Exhaust>::exhaust_factories()
}
};
}
pub(crate) use delegate_factory_and_iter;
macro_rules! impl_singleton {
([$($generics:tt)*], $self:ty) => {
impl<$($generics)*> $crate::Exhaust for $self {
type Iter = ::core::iter::Once<()>;
type Factory = ();
fn exhaust_factories() -> Self::Iter {
::core::iter::once(())
}
fn from_factory((): Self::Factory) -> Self {
::core::default::Default::default()
}
}
};
([$($generics:tt)*], $self:ty, $ctor:expr) => {
impl<$($generics)*> $crate::Exhaust for $self {
type Iter = ::core::iter::Once<()>;
type Factory = ();
fn exhaust_factories() -> Self::Iter {
::core::iter::once(())
}
fn from_factory((): Self::Factory) -> Self {
$ctor
}
}
};
}
pub(crate) use impl_singleton;
macro_rules! impl_via_array {
($self:ty, $array:expr) => {
const _: () = {
impl $crate::Exhaust for $self {
type Iter = ExhaustIter;
fn exhaust_factories() -> Self::Iter {
#![allow(clippy::cast_possible_truncation)]
const {
assert!(VALUES.len() < u8::MAX as usize);
ExhaustIter {
index_iter: 0..{ VALUES.len() as u8 },
}
}
}
$crate::patterns::factory_is_self!();
}
const VALUES: &[$self; $array.len()] = &$array;
#[derive(Clone, Debug)] pub struct ExhaustIter {
index_iter: ::core::ops::Range<u8>,
}
impl Iterator for ExhaustIter {
type Item = $self;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.index_iter.next() {
Some(index) => Some(VALUES[usize::from(index)]),
None => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.index_iter.size_hint()
}
}
impl DoubleEndedIterator for ExhaustIter {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
match self.index_iter.next_back() {
Some(index) => Some(VALUES[usize::from(index)]),
None => None,
}
}
}
impl ::core::iter::FusedIterator for ExhaustIter {}
impl ::core::iter::ExactSizeIterator for ExhaustIter where
::core::ops::Range<u8>: ::core::iter::ExactSizeIterator
{
}
};
};
}
pub(crate) use impl_via_array;
macro_rules! impl_via_range {
($self:ty, $start:expr, $end:expr) => {
impl $crate::Exhaust for $self {
type Iter = ::core::ops::RangeInclusive<$self>;
fn exhaust_factories() -> Self::Iter {
(($start)..=($end))
}
$crate::patterns::factory_is_self!();
}
};
}
pub(crate) use impl_via_range;
macro_rules! impl_newtype_generic {
($tvar:ident : [ $( $bounds:tt )* ] , $container:ty, $wrap_fn:expr) => {
impl<$tvar: $crate::Exhaust> $crate::Exhaust for $container
where
$tvar: $( $bounds )*
{
type Iter = <$tvar as $crate::Exhaust>::Iter;
fn exhaust_factories() -> Self::Iter {
<$tvar as $crate::Exhaust>::exhaust_factories()
}
type Factory = <$tvar as $crate::Exhaust>::Factory;
fn from_factory(factory: Self::Factory) -> Self {
$wrap_fn(<$tvar as $crate::Exhaust>::from_factory(factory))
}
}
};
}
pub(crate) use impl_newtype_generic;
macro_rules! impl_iterator_for_newtype {
(
[$($generics:tt)*] for $iterator_type:ty {
type Item = $item_type:ty;
fn mapper = $mapping_function:expr;
double_ended_where [$($double_ended_bounds:tt)*];
}
) => {
$crate::patterns::impl_iterator_for_newtype!([$($generics)*] for $iterator_type {
type Item = $item_type;
fn mapper = $mapping_function;
not_double_ended;
});
impl<$($generics)*> DoubleEndedIterator for $iterator_type
where $($double_ended_bounds)* {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map($mapping_function)
}
fn rfold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.0.rfold(init, |state, inner_item| {
f(state, ($mapping_function)(inner_item))
})
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.0.nth_back(n).map($mapping_function)
}
}
};
(
[$($generics:tt)*] for $iterator_type:ty {
type Item = $item_type:ty;
fn mapper = $mapping_function:expr;
not_double_ended;
}
) => {
impl<$($generics)*> Iterator for $iterator_type {
type Item = $item_type;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map($mapping_function)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn fold<B, F>(self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
self.0.fold(init, |state, inner_item| {
f(state, ($mapping_function)(inner_item))
})
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.0.nth(n).map($mapping_function)
}
fn last(self) -> Option<Self::Item> {
self.0.last().map($mapping_function)
}
}
};
}
pub(crate) use impl_iterator_for_newtype;