use super::{AggregateItem, AggregateType, IAggregateChangeSet};
use crate::list::ListChangeReason;
use crate::ChangeReason;
use std::rc::Rc;
pub(crate) struct AggregateEnumerator<T> {
source: crate::list::ChangeSet<T>,
}
impl<T> AggregateEnumerator<T> {
pub(crate) fn new(source: crate::list::ChangeSet<T>) -> Self {
Self { source }
}
}
impl<T: Clone> IAggregateChangeSet<T> for AggregateEnumerator<T> {
fn items(&self) -> Box<dyn Iterator<Item = AggregateItem<T>> + '_> {
Box::new(self.source.changes().iter().flat_map(|change| -> Vec<AggregateItem<T>> {
match change.reason() {
ListChangeReason::Add => vec![AggregateItem::new(AggregateType::Add, change.item().current().clone())],
ListChangeReason::AddRange => change.range().iter().map(|item| AggregateItem::new(AggregateType::Add, item.clone())).collect(),
ListChangeReason::Replace => {
let previous = change.item().previous().expect("a Replace has the previous item").clone();
vec![AggregateItem::new(AggregateType::Remove, previous), AggregateItem::new(AggregateType::Add, change.item().current().clone())]
}
ListChangeReason::Remove => vec![AggregateItem::new(AggregateType::Remove, change.item().current().clone())],
ListChangeReason::RemoveRange | ListChangeReason::Clear => {
change.range().iter().map(|item| AggregateItem::new(AggregateType::Remove, item.clone())).collect()
}
ListChangeReason::Refresh | ListChangeReason::Moved => Vec::new(),
}
}))
}
}
pub(crate) struct CacheAggregateEnumerator<T, K> {
source: crate::cache::ChangeSet<T, K>,
}
impl<T, K> CacheAggregateEnumerator<T, K> {
pub(crate) fn new(source: crate::cache::ChangeSet<T, K>) -> Self {
Self { source }
}
}
impl<T: Clone, K> IAggregateChangeSet<T> for CacheAggregateEnumerator<T, K> {
fn items(&self) -> Box<dyn Iterator<Item = AggregateItem<T>> + '_> {
Box::new(self.source.changes().iter().flat_map(|change| -> Vec<AggregateItem<T>> {
match change.reason() {
ChangeReason::Add => vec![AggregateItem::new(AggregateType::Add, change.current().clone())],
ChangeReason::Update => {
let previous = change.previous().expect("an Update has the previous item").clone();
vec![AggregateItem::new(AggregateType::Remove, previous), AggregateItem::new(AggregateType::Add, change.current().clone())]
}
ChangeReason::Remove => vec![AggregateItem::new(AggregateType::Remove, change.current().clone())],
_ => Vec::new(),
}
}))
}
}
pub(crate) fn list_aggregate<T: Clone + 'static>(changes: crate::list::ChangeSet<T>) -> Rc<dyn IAggregateChangeSet<T>> {
Rc::new(AggregateEnumerator::new(changes))
}
pub(crate) fn cache_aggregate<T: Clone + 'static, K: 'static>(changes: crate::cache::ChangeSet<T, K>) -> Rc<dyn IAggregateChangeSet<T>> {
Rc::new(CacheAggregateEnumerator::new(changes))
}