use crate::sync::RwLock;
pub struct Storage<T> {
val: RwLock<Option<T>>,
}
const ERR_EMPTY: &str = "storage empty";
impl<T> Storage<T> {
pub fn new(val: T) -> Self {
Storage {
val: RwLock::new(Some(val)),
}
}
pub fn get(&self) -> T
where
T: Clone,
{
self.val.read().clone().expect(ERR_EMPTY)
}
pub fn set(&self, val: T) {
*self.val.write() = Some(val);
}
pub fn replace<F>(&self, f: F)
where
F: FnOnce(T) -> T,
{
let mut st = self.val.write();
let old = st.take().expect(ERR_EMPTY);
*st = Some(f(old));
}
pub fn replace_fetch<F>(&self, f: F) -> T
where
F: FnOnce(T) -> T,
T: Clone,
{
let mut st = self.val.write();
let old = st.take().expect(ERR_EMPTY);
let new = f(old);
*st = Some(new.clone());
new
}
pub fn replace_clone<F>(&self, f: F)
where
F: FnOnce(T) -> T,
T: Clone,
{
let mut st = self.val.write();
let old = st.clone().expect(ERR_EMPTY);
*st = Some(f(old));
}
}
impl<T> Default for Storage<T> {
fn default() -> Self {
Storage {
val: Default::default(),
}
}
}