use std::ops::{Deref, DerefMut};
const MISSING_CONTEXT: &str = "runtime context missing";
const DUPLICATE_CONTEXT: &str = "runtime context already present";
#[macro_export]
macro_rules! spawn_cell {
($cell:expr, $body:expr $(,)?) => {{
let __commonware_context = $cell.take();
$crate::Spawner::spawn(__commonware_context, move |context| {
$cell.restore(context);
$body
})
}};
}
#[derive(Debug)]
pub enum Cell<C> {
Present(C),
Missing,
}
impl<C> Cell<C> {
pub const fn new(context: C) -> Self {
Self::Present(context)
}
pub fn take(&mut self) -> C {
match std::mem::replace(self, Self::Missing) {
Self::Present(context) => context,
Self::Missing => panic!("{}", MISSING_CONTEXT),
}
}
pub fn restore(&mut self, context: C) {
match self {
Self::Present(_) => panic!("{}", DUPLICATE_CONTEXT),
Self::Missing => {
*self = Self::Present(context);
}
}
}
pub fn as_present(&self) -> &C {
match self {
Self::Present(context) => context,
Self::Missing => panic!("{}", MISSING_CONTEXT),
}
}
pub fn as_present_mut(&mut self) -> &mut C {
match self {
Self::Present(context) => context,
Self::Missing => panic!("{}", MISSING_CONTEXT),
}
}
pub fn into_present(self) -> C {
match self {
Self::Present(context) => context,
Self::Missing => panic!("{}", MISSING_CONTEXT),
}
}
}
impl<C> Deref for Cell<C> {
type Target = C;
fn deref(&self) -> &C {
self.as_present()
}
}
impl<C> DerefMut for Cell<C> {
fn deref_mut(&mut self) -> &mut C {
self.as_present_mut()
}
}
impl<C> AsRef<C> for Cell<C> {
fn as_ref(&self) -> &C {
self.as_present()
}
}
impl<C> AsMut<C> for Cell<C> {
fn as_mut(&mut self) -> &mut C {
self.as_present_mut()
}
}