use std::{hash::Hash, ops};
use readlock::Shared;
use crate::{state::ObservableState, Subscriber};
#[derive(Debug)]
pub struct Observable<T> {
state: Shared<ObservableState<T>>,
}
impl<T> Observable<T> {
#[must_use]
pub fn new(value: T) -> Self {
Self { state: Shared::new(ObservableState::new(value)) }
}
pub fn subscribe(this: &Self) -> Subscriber<T> {
Subscriber::new(Shared::get_read_lock(&this.state), this.state.version())
}
pub fn subscribe_reset(this: &Self) -> Subscriber<T> {
Subscriber::new(Shared::get_read_lock(&this.state), 0)
}
pub fn get(this: &Self) -> &T {
this.state.get()
}
pub fn set(this: &mut Self, value: T) -> T {
Shared::lock(&mut this.state).set(value)
}
pub fn set_if_not_eq(this: &mut Self, value: T) -> Option<T>
where
T: PartialEq,
{
Shared::lock(&mut this.state).set_if_not_eq(value)
}
pub fn set_if_hash_not_eq(this: &mut Self, value: T) -> Option<T>
where
T: Hash,
{
Shared::lock(&mut this.state).set_if_hash_not_eq(value)
}
pub fn take(this: &mut Self) -> T
where
T: Default,
{
Self::set(this, T::default())
}
pub fn update(this: &mut Self, f: impl FnOnce(&mut T)) {
Shared::lock(&mut this.state).update(f);
}
pub fn update_if(this: &mut Self, f: impl FnOnce(&mut T) -> bool) {
Shared::lock(&mut this.state).update_if(f);
}
#[must_use]
pub fn subscriber_count(&self) -> usize {
Shared::read_count(&self.state)
}
}
impl<T: Default> Default for Observable<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> ops::Deref for Observable<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.state.get()
}
}
impl<T> Drop for Observable<T> {
fn drop(&mut self) {
Shared::lock(&mut self.state).close();
}
}