use super::{node::ReactiveNode, AnySubscriber};
use crate::traits::{DefinedAt, IsDisposed};
use core::{fmt::Debug, hash::Hash};
use std::{panic::Location, sync::Weak};
pub trait ToAnySource: IsDisposed {
fn to_any_source(&self) -> AnySource;
}
pub trait Source: ReactiveNode {
fn add_subscriber(&self, subscriber: AnySubscriber);
fn remove_subscriber(&self, subscriber: &AnySubscriber);
fn clear_subscribers(&self);
}
#[derive(Clone)]
pub struct AnySource(
pub(crate) usize,
pub(crate) Weak<dyn Source + Send + Sync>,
#[cfg(any(debug_assertions, leptos_debuginfo))]
pub(crate) &'static Location<'static>,
);
impl DefinedAt for AnySource {
fn defined_at(&self) -> Option<&'static Location<'static>> {
#[cfg(any(debug_assertions, leptos_debuginfo))]
{
Some(self.2)
}
#[cfg(not(any(debug_assertions, leptos_debuginfo)))]
{
None
}
}
}
impl Debug for AnySource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("AnySource").field(&self.0).finish()
}
}
impl Hash for AnySource {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl PartialEq for AnySource {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for AnySource {}
impl IsDisposed for AnySource {
#[inline(always)]
fn is_disposed(&self) -> bool {
false
}
}
impl ToAnySource for AnySource {
fn to_any_source(&self) -> AnySource {
self.clone()
}
}
impl Source for AnySource {
fn add_subscriber(&self, subscriber: AnySubscriber) {
if let Some(inner) = self.1.upgrade() {
inner.add_subscriber(subscriber)
}
}
fn remove_subscriber(&self, subscriber: &AnySubscriber) {
if let Some(inner) = self.1.upgrade() {
inner.remove_subscriber(subscriber)
}
}
fn clear_subscribers(&self) {
if let Some(inner) = self.1.upgrade() {
inner.clear_subscribers();
}
}
}
impl ReactiveNode for AnySource {
fn mark_dirty(&self) {
if let Some(inner) = self.1.upgrade() {
inner.mark_dirty()
}
}
fn mark_subscribers_check(&self) {
if let Some(inner) = self.1.upgrade() {
inner.mark_subscribers_check()
}
}
fn update_if_necessary(&self) -> bool {
if let Some(inner) = self.1.upgrade() {
inner.update_if_necessary()
} else {
false
}
}
fn mark_check(&self) {
if let Some(inner) = self.1.upgrade() {
inner.mark_check()
}
}
}