use std::{ops::Deref, rc::Rc};
use crate::ObservableCell;
#[derive(Debug)]
pub struct Guarded<T> {
value: T,
guard: Guard,
}
impl<T> Guarded<T> {
pub(super) fn wrap(value: T, counter: Rc<ObservableCell<u32>>) -> Self {
Self { value, guard: Guard::new(counter) }
}
#[must_use]
pub fn into_parts(self) -> (T, Guard) {
(self.value, self.guard)
}
#[must_use]
pub fn into_inner(self) -> T {
self.value
}
}
impl<T> Guarded<Option<T>> {
#[must_use]
pub fn transpose(self) -> Option<Guarded<T>> {
let (value, guard) = self.into_parts();
value.map(move |v| Guarded { value: v, guard })
}
}
impl<T> AsRef<T> for Guarded<T> {
fn as_ref(&self) -> &T {
&self.value
}
}
impl<T> Deref for Guarded<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
#[derive(Debug)]
pub struct Guard(Rc<ObservableCell<u32>>);
impl Guard {
fn new(counter: Rc<ObservableCell<u32>>) -> Self {
#[expect(clippy::expect_used, reason = "overflowing is unexpected")]
counter.mutate(|mut c| {
*c = c
.checked_add(1)
.expect("`progressable::Guard` counter overflow");
});
Self(counter)
}
}
impl Drop for Guard {
fn drop(&mut self) {
self.0.mutate(|mut c| {
*c = c.saturating_sub(1);
});
}
}