use std::{
any::type_name,
fmt,
sync::{Arc, RwLock},
};
#[derive(Clone)]
pub struct Changeable<T>(Arc<RwLock<T>>);
impl<T> Changeable<T>
where
T: Clone + Send,
{
#[must_use]
pub fn new(value: T) -> Self {
Self(Arc::new(RwLock::new(value)))
}
pub fn replace(&self, new: T) {
*(self.0.write().expect("changeable lock poisoned")) = new;
}
#[must_use]
pub fn get(&self) -> T {
self.0.read().expect("handler lock poisoned").clone()
}
}
impl<T> Default for Changeable<T>
where
T: Clone + Send + Default,
{
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> fmt::Debug for Changeable<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Changeable")
.field("inner type", &type_name::<T>())
.finish_non_exhaustive()
}
}
pub struct ChangeableFn<T, U>(Changeable<Arc<dyn (Fn(T) -> U) + Send + Sync>>);
impl<T, U> ChangeableFn<T, U>
where
T: Send,
U: Send,
{
pub(crate) fn new(f: impl (Fn(T) -> U) + Send + Sync + 'static) -> Self {
Self(Changeable::new(Arc::new(f)))
}
pub fn replace(&self, new: impl (Fn(T) -> U) + Send + Sync + 'static) {
self.0.replace(Arc::new(new));
}
pub fn call(&self, data: T) -> U {
(self.0.get())(data)
}
}
impl<T, U> Clone for ChangeableFn<T, U> {
fn clone(&self) -> Self {
Self(Changeable::clone(&self.0))
}
}
impl<T, U> Default for ChangeableFn<T, U>
where
T: Send,
U: Send + Default,
{
fn default() -> Self {
Self::new(|_| U::default())
}
}
impl<T, U> fmt::Debug for ChangeableFn<T, U> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ChangeableFn")
.field("payload type", &type_name::<T>())
.field("return type", &type_name::<U>())
.finish_non_exhaustive()
}
}