use crate::theme::BarPosition;
use crate::theme::Color;
use crate::theme::ContainerBordersSetting;
use crate::utils::clonecell::CloneCell;
use linearize::Linearize;
use linearize::StaticCopyMap;
use linearize::StaticMap;
use static_assertions::const_assert;
use std::cell::Cell;
use std::fmt::Debug;
use std::mem::ManuallyDrop;
use std::rc::Rc;
use std::sync::Arc;
pub trait CachedDefault: Sized {
fn cached_default() -> Self;
}
pub trait CachedValue: CachedDefault {
type Changed: Copy + Debug + Default;
type Op;
fn cached_set(&self, v: Self);
fn cached_apply(&self, v: Self::Op);
fn cached_update(&self, v: Self, handle_change: impl FnMut(Self::Op)) -> Self::Changed;
}
impl<V> CachedDefault for Cell<V>
where
V: CachedDefault,
{
fn cached_default() -> Self {
Cell::new(V::cached_default())
}
}
impl<V> CachedValue for Cell<V>
where
V: CachedDefault + Copy + PartialEq,
{
type Changed = bool;
type Op = V;
fn cached_set(&self, v: Self) {
self.set(v.into_inner());
}
fn cached_apply(&self, v: Self::Op) {
self.set(v);
}
fn cached_update(&self, v: Self, mut handle_change: impl FnMut(Self::Op)) -> Self::Changed {
let v = v.get();
let changed = self.replace(v) != v;
if changed {
handle_change(v);
}
changed
}
}
impl<V> CachedDefault for CloneCell<V>
where
V: CachedDefault,
{
fn cached_default() -> Self {
CloneCell::new(V::cached_default())
}
}
impl<T> CachedValue for CloneCell<T>
where
T: CachedDefault + Clone + PartialEq,
{
type Changed = bool;
type Op = T;
fn cached_set(&self, v: Self) {
self.set(v.into_inner());
}
fn cached_apply(&self, v: Self::Op) {
self.set(v);
}
fn cached_update(&self, v: Self, mut handle_change: impl FnMut(Self::Op)) -> Self::Changed {
let v = v.into_inner();
let old = self.set(v.clone());
let changed = old != v;
if changed {
handle_change(v);
}
changed
}
}
impl<K, V> CachedDefault for StaticMap<K, V>
where
K: Linearize,
V: CachedDefault,
{
fn cached_default() -> Self {
StaticMap::from_fn(|_| V::cached_default())
}
}
impl<K, V> CachedValue for StaticMap<K, V>
where
K: Linearize + Copy + Debug,
V: CachedValue,
{
type Changed = StaticCopyMap<K, V::Changed>;
type Op = (K, V::Op);
fn cached_set(&self, v: Self) {
for (k, v) in v {
V::cached_set(&self[k], v);
}
}
fn cached_apply(&self, (k, v): Self::Op) {
V::cached_apply(&self[k], v);
}
fn cached_update(&self, v: Self, mut handle_change: impl FnMut(Self::Op)) -> Self::Changed {
let mut changed = StaticCopyMap::default();
for (k, v) in v {
changed[k] = V::cached_update(&self[k], v, |c| {
handle_change((k, c));
});
}
changed
}
}
macro_rules! default {
($($ty:ty,)*) => {
$(
impl CachedDefault for $ty {
fn cached_default() -> Self {
Default::default()
}
}
)*
};
}
default! {
i32,
bool,
ContainerBordersSetting,
BarPosition,
}
impl CachedDefault for Color {
fn cached_default() -> Self {
Color::TRANSPARENT
}
}
impl CachedDefault for Rc<Arc<str>> {
fn cached_default() -> Self {
type T = ManuallyDrop<Rc<Arc<str>>>;
const_assert!(!std::mem::needs_drop::<T>());
thread_local! {
static EMPTY_STRING: T = Default::default();
}
EMPTY_STRING.with(|v| (**v).clone())
}
}