use std::{any::Any, sync::Arc}; use tokio::sync::{Mutex, MutexGuard, mpsc::Sender}; pub struct Refresh; pub struct Close; #[derive(Debug, Clone)] pub struct Context { pub(crate) tx: Sender>, } #[derive(Debug)] pub struct State { pub value: Arc>, tx: Sender>, } pub struct StateGuard<'a, T> { is_mutated: bool, value: MutexGuard<'a, T>, tx: &'a Sender>, } impl Context { pub fn use_state(&self, v: T) -> State { State { value: Arc::new(Mutex::new(v)), tx: self.tx.clone(), } } } impl State { pub async fn lock<'a>(&'a self) -> StateGuard<'a, T> { StateGuard { value: self.value.lock().await, is_mutated: false, tx: &self.tx, } } } impl State { pub async fn display(&self) -> String { self.lock().await.to_string() } } impl Clone for State { fn clone(&self) -> Self { State { value: self.value.clone(), tx: self.tx.clone(), } } } impl<'a, T> std::ops::Deref for StateGuard<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { &self.value } } impl<'a, T> std::ops::DerefMut for StateGuard<'a, T> { fn deref_mut(&mut self) -> &mut Self::Target { self.is_mutated = true; &mut self.value } } impl<'a, T> Drop for StateGuard<'a, T> { fn drop(&mut self) { if self.is_mutated { let tx = self.tx.clone(); tokio::spawn(async move { tx.send(Box::new(Refresh)).await.unwrap() }); } } } impl Context { pub async fn close(&self) { self.tx.send(Box::new(Close)).await.unwrap() } }