use super::{AsyncClerk, Changes, Clerk, Key, Token, TokenChanges, TokenClerk};
use kas::Id;
use kas::event::ConfigCx;
#[allow(unused)] use kas::{Events, Widget};
use std::fmt::Debug;
use std::ops::Range;
#[derive(Clone, Debug, PartialEq, Eq)]
#[must_use]
pub enum GeneratorChanges<Index> {
None,
LenOnly,
Range(Range<Index>),
Any,
}
pub trait IndexedGenerator<Index>: Clerk<Index, Item: Clone + Default + PartialEq> {
fn update(&mut self, data: &Self::Data) -> GeneratorChanges<Index>;
fn generate(&self, data: &Self::Data, index: Index) -> Self::Item;
}
pub trait KeyedGenerator<Index>: Clerk<Index, Item: Clone + Default + PartialEq> {
type Key: Key;
fn update(&mut self, data: &Self::Data) -> GeneratorChanges<Index>;
fn key(&self, data: &Self::Data, index: Index) -> Option<Self::Key>;
fn generate(&self, data: &Self::Data, key: &Self::Key) -> Self::Item;
}
impl<Index: Key, G: IndexedGenerator<Index>> KeyedGenerator<Index> for G {
type Key = Index;
fn update(&mut self, data: &Self::Data) -> GeneratorChanges<Index> {
self.update(data)
}
fn key(&self, _: &Self::Data, index: Index) -> Option<Self::Key> {
Some(index)
}
fn generate(&self, data: &Self::Data, key: &Self::Key) -> Self::Item {
self.generate(data, key.clone())
}
}
impl<Index, G: KeyedGenerator<Index>> AsyncClerk<Index> for G {
type Key = G::Key;
fn update(
&mut self,
_: &mut ConfigCx,
_: Id,
_: Range<Index>,
data: &Self::Data,
) -> Changes<Index> {
match self.update(data) {
GeneratorChanges::None => Changes::None,
GeneratorChanges::LenOnly => Changes::NoPreparedItems,
GeneratorChanges::Range(range) => Changes::Range(range),
GeneratorChanges::Any => Changes::Any,
}
}
}
impl<Index, G: KeyedGenerator<Index>> TokenClerk<Index> for G {
type Token = Token<Self::Key, Self::Item>;
fn update_token(
&self,
data: &Self::Data,
index: Index,
update_item: bool,
token: &mut Option<Self::Token>,
) -> TokenChanges {
let Some(key) = self.key(data, index) else {
*token = None;
return TokenChanges::None;
};
if !update_item
&& let Some(token) = token.as_mut()
&& token.key == key
{
return TokenChanges::None;
}
let item = self.generate(data, &key);
let mut changes = TokenChanges::Any;
if let Some(token) = token.as_mut()
&& token.key == key
{
if token.item == item {
return TokenChanges::None;
} else {
changes = TokenChanges::SameKey;
}
}
*token = Some(Token { key, item });
changes
}
#[inline]
fn item<'r>(&'r self, _: &'r Self::Data, token: &'r Self::Token) -> &'r Self::Item {
&token.item
}
}