use super::*;
#[derive(CustomDebug, Data, New)]
pub(crate) struct SignalInner<T>
where
T: Clone,
{
#[debug(skip)]
#[get(pub(crate))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) value: T,
#[debug(skip)]
#[get(pub(crate))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) listeners: Vec<Box<dyn FnMut()>>,
#[get(pub, type(copy))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) alive: bool,
#[debug(skip)]
#[get(pub(crate))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
#[new(skip)]
pub(crate) dependents: Vec<usize>,
#[get(pub, type(copy))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
#[new(skip)]
pub(crate) listeners_replaced: bool,
}
#[derive(CustomDebug, Data, Eq, Hash, New, Ord, PartialEq, PartialOrd)]
pub struct Signal<T>
where
T: Clone + PartialEq + 'static,
{
#[debug(skip)]
#[get(pub, type(copy))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) inner: usize,
#[debug(skip)]
#[get(pub, type(copy))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) _marker: PhantomData<fn() -> T>,
}
#[derive(CustomDebug, Data, New)]
pub struct SignalCell<T>
where
T: Clone + PartialEq + 'static,
{
#[debug(skip)]
#[get(pub(crate))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) inner: UnsafeCell<Option<Signal<T>>>,
}
#[derive(Data, Debug, New)]
pub(crate) struct BridgeRefsCell(
#[get(pub(crate))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub UnsafeCell<HashMap<usize, HashSet<usize>>>,
);
#[derive(Clone, Copy, CustomDebug, Data, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct FireHandle {
#[get(pub, type(copy))]
#[get_mut(pub(crate))]
#[set(pub(crate))]
pub(crate) inner: usize,
}
pub(crate) struct SignalSlab {
pub(crate) entries: Vec<SignalSlot>,
pub(crate) free_head: usize,
}
impl SignalSlab {
pub(crate) fn new() -> Self {
Self {
entries: Vec::new(),
free_head: usize::MAX,
}
}
pub(crate) fn insert<T>(&mut self, inner: SignalInner<T>) -> usize
where
T: Clone + PartialEq + 'static,
{
let boxed: Box<dyn AnySignalInner> = Box::new(inner);
if self.free_head != usize::MAX {
let idx: usize = self.free_head;
let next: usize = match &self.entries[idx] {
SignalSlot::Free { next } => *next,
SignalSlot::Occupied(_) => {
self.free_head = usize::MAX;
let new_idx: usize = self.entries.len();
self.entries.push(SignalSlot::Occupied(boxed));
return new_idx;
}
};
self.free_head = next;
self.entries[idx] = SignalSlot::Occupied(boxed);
idx
} else {
let idx: usize = self.entries.len();
self.entries.push(SignalSlot::Occupied(boxed));
idx
}
}
pub(crate) fn get_mut<T>(&mut self, idx: usize) -> Option<&mut SignalInner<T>>
where
T: Clone + PartialEq + 'static,
{
match self.entries.get_mut(idx)? {
SignalSlot::Occupied(slot) => {
let any: &mut dyn Any = (**slot).as_any_mut();
any.downcast_mut::<SignalInner<T>>()
}
SignalSlot::Free { .. } => None,
}
}
pub(crate) fn is_alive(&self, idx: usize) -> bool {
match self.entries.get(idx) {
Some(SignalSlot::Occupied(inner)) => inner.alive(),
Some(SignalSlot::Free { .. }) => false,
None => false,
}
}
pub(crate) fn free(&mut self, idx: usize) {
if let Some(slot @ SignalSlot::Occupied(_)) = self.entries.get_mut(idx) {
*slot = SignalSlot::Free {
next: self.free_head,
};
self.free_head = idx;
}
}
pub(crate) fn deactivate(&mut self, idx: usize) {
if let Some(SignalSlot::Occupied(inner)) = self.entries.get_mut(idx) {
inner.set_inactive();
}
}
}