use std::{
cell::{Ref, RefCell, RefMut},
hash::Hash,
ops::{Deref, DerefMut},
rc::Rc,
sync::{Arc, Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use crate::{Observable, Subscriber};
#[derive(Clone, Debug)]
pub struct SharedObservableBase<L>(pub L);
impl<T, L> SharedObservableBase<L>
where
L: ObservableLock<Item = T>,
{
pub fn new(value: T) -> Self {
Self(L::from_observable(Observable::new(value)))
}
pub fn subscribe(&self) -> Subscriber<T> {
Observable::subscribe(&self.read())
}
pub fn read(&self) -> L::ReadGuard<'_> {
self.0.read()
}
pub fn write(&self) -> L::WriteGuard<'_> {
self.0.write()
}
pub fn get(&self) -> T
where
T: Clone,
{
self.read().clone()
}
pub fn set(&self, value: T) {
Observable::set(&mut self.write(), value);
}
pub fn set_eq(&self, value: T)
where
T: Clone + PartialEq,
{
Observable::set_eq(&mut self.write(), value);
}
pub fn set_hash(&self, value: T)
where
T: Hash,
{
Observable::set_hash(&mut self.write(), value);
}
pub fn replace(&self, value: T) -> T {
Observable::replace(&mut self.write(), value)
}
pub fn take(&self) -> T
where
T: Default,
{
Observable::take(&mut self.write())
}
pub fn update(&self, f: impl FnOnce(&mut T)) {
Observable::update(&mut self.write(), f);
}
pub fn update_eq(&self, f: impl FnOnce(&mut T))
where
T: Clone + PartialEq,
{
Observable::update_eq(&mut self.write(), f);
}
pub fn update_hash(&self, f: impl FnOnce(&mut T))
where
T: Hash,
{
Observable::update_hash(&mut self.write(), f);
}
}
impl<T, I> Default for SharedObservableBase<I>
where
T: Default,
I: ObservableLock<Item = T>,
{
fn default() -> Self {
Self::new(T::default())
}
}
pub trait ObservableLock {
type Item;
type ReadGuard<'a>: Deref<Target = Observable<Self::Item>>
where
Self: 'a;
type WriteGuard<'a>: DerefMut<Target = Observable<Self::Item>>
where
Self: 'a;
fn from_observable(ob: Observable<Self::Item>) -> Self;
fn read(&self) -> Self::ReadGuard<'_>;
fn write(&self) -> Self::WriteGuard<'_>;
}
impl<T> ObservableLock for RefCell<Observable<T>> {
type Item = T;
type ReadGuard<'a> = Ref<'a, Observable<T>>
where Self: 'a;
type WriteGuard<'a> = RefMut<'a, Observable<T>>
where
Self: 'a;
fn from_observable(ob: Observable<Self::Item>) -> Self {
Self::new(ob)
}
fn read(&self) -> Self::ReadGuard<'_> {
self.borrow()
}
fn write(&self) -> Self::WriteGuard<'_> {
self.borrow_mut()
}
}
impl<T> ObservableLock for Mutex<Observable<T>> {
type Item = T;
type ReadGuard<'a> = MutexGuard<'a, Observable<T>>
where
Self: 'a;
type WriteGuard<'a> = MutexGuard<'a, Observable<T>>
where
Self: 'a;
fn from_observable(ob: Observable<Self::Item>) -> Self {
Self::new(ob)
}
fn read(&self) -> Self::ReadGuard<'_> {
self.lock().unwrap()
}
fn write(&self) -> Self::WriteGuard<'_> {
self.lock().unwrap()
}
}
impl<T> ObservableLock for RwLock<Observable<T>> {
type Item = T;
type ReadGuard<'a> = RwLockReadGuard<'a, Observable<T>>
where
Self: 'a;
type WriteGuard<'a> = RwLockWriteGuard<'a, Observable<T>>
where
Self: 'a;
fn from_observable(ob: Observable<Self::Item>) -> Self {
Self::new(ob)
}
fn read(&self) -> Self::ReadGuard<'_> {
self.read().unwrap()
}
fn write(&self) -> Self::WriteGuard<'_> {
self.write().unwrap()
}
}
impl<L: ObservableLock> ObservableLock for Rc<L> {
type Item = L::Item;
type ReadGuard<'a> = L::ReadGuard<'a>
where
Self: 'a;
type WriteGuard<'a> = L::WriteGuard<'a>
where
Self: 'a;
fn from_observable(ob: Observable<Self::Item>) -> Self {
Self::new(L::from_observable(ob))
}
fn read(&self) -> Self::ReadGuard<'_> {
(**self).read()
}
fn write(&self) -> Self::WriteGuard<'_> {
(**self).write()
}
}
impl<L: ObservableLock> ObservableLock for Arc<L> {
type Item = L::Item;
type ReadGuard<'a> = L::ReadGuard<'a>
where
Self: 'a;
type WriteGuard<'a> = L::WriteGuard<'a>
where
Self: 'a;
fn from_observable(ob: Observable<Self::Item>) -> Self {
Self::new(L::from_observable(ob))
}
fn read(&self) -> Self::ReadGuard<'_> {
(**self).read()
}
fn write(&self) -> Self::WriteGuard<'_> {
(**self).write()
}
}