#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#[derive(Debug, Copy, Clone)]
pub struct ImplReduce<Item> {
item: Option<Item>,
}
pub trait ReduceTrait<Item> {
fn reduce(lhs: Item, rhs: Item) -> Item;
}
impl<Item> ImplReduce<Item> {
pub fn new(initial: Item) -> Self {
Self {
item: Some(initial),
}
}
pub fn into_inner(self) -> Option<Item> {
self.item
}
pub fn as_ref(&self) -> Option<&Item> {
self.item.as_ref()
}
pub fn reduce(&mut self, item: Item)
where
Self: ReduceTrait<Item>,
{
if let Some(current_item) = self.item.take() {
self.item = Some(<Self as ReduceTrait<Item>>::reduce(current_item, item));
} else {
self.item = Some(item);
}
}
}
impl<Item> From<Item> for ImplReduce<Item> {
fn from(item: Item) -> Self {
Self::new(item)
}
}
impl<Item> Extend<Item> for ImplReduce<Item>
where
ImplReduce<Item>: ReduceTrait<Item>,
{
fn extend<It: IntoIterator<Item = Item>>(&mut self, iter: It) {
iter.into_iter().for_each(|i| self.reduce(i));
}
}
impl<Item> Default for ImplReduce<Item> {
fn default() -> Self {
Self { item: None }
}
}
impl<Item> std::iter::FromIterator<Item> for ImplReduce<Item>
where
ImplReduce<Item>: ReduceTrait<Item>,
{
fn from_iter<It: IntoIterator<Item = Item>>(iter: It) -> Self {
let mut autofolder = Self::default();
autofolder.extend(iter);
autofolder
}
}
#[macro_export]
macro_rules! autofolder_impl_reducetrait{
(|$a:ident , $i:ident| -> $item_type: ty $body: block) => {
impl ReduceTrait<$item_type> for ImplReduce<$item_type> {
fn reduce(mut $a: $item_type, $i: $item_type) -> $item_type $body
}
}
}