use super::{
guards::{Plain, ReadGuard},
subscriber_traits::AsSubscriberSet,
ArcReadSignal,
};
use crate::{
graph::SubscriberSet,
owner::{ArenaItem, FromLocal, LocalStorage, Storage, SyncStorage},
traits::{DefinedAt, Dispose, IntoInner, IsDisposed, ReadUntracked},
unwrap_signal,
};
use core::fmt::Debug;
use std::{
hash::Hash,
panic::Location,
sync::{Arc, RwLock},
};
pub struct ReadSignal<T, S = SyncStorage> {
#[cfg(any(debug_assertions, leptos_debuginfo))]
pub(crate) defined_at: &'static Location<'static>,
pub(crate) inner: ArenaItem<ArcReadSignal<T>, S>,
}
impl<T, S> Dispose for ReadSignal<T, S> {
fn dispose(self) {
self.inner.dispose()
}
}
impl<T, S> Copy for ReadSignal<T, S> {}
impl<T, S> Clone for ReadSignal<T, S> {
fn clone(&self) -> Self {
*self
}
}
impl<T, S> Debug for ReadSignal<T, S>
where
S: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ReadSignal")
.field("type", &std::any::type_name::<T>())
.field("store", &self.inner)
.finish()
}
}
impl<T, S> PartialEq for ReadSignal<T, S> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<T, S> Eq for ReadSignal<T, S> {}
impl<T, S> Hash for ReadSignal<T, S> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
impl<T, S> DefinedAt for ReadSignal<T, S> {
fn defined_at(&self) -> Option<&'static Location<'static>> {
#[cfg(any(debug_assertions, leptos_debuginfo))]
{
Some(self.defined_at)
}
#[cfg(not(any(debug_assertions, leptos_debuginfo)))]
{
None
}
}
}
impl<T, S> IsDisposed for ReadSignal<T, S> {
fn is_disposed(&self) -> bool {
self.inner.is_disposed()
}
}
impl<T, S> IntoInner for ReadSignal<T, S>
where
S: Storage<ArcReadSignal<T>>,
{
type Value = T;
#[inline(always)]
fn into_inner(self) -> Option<Self::Value> {
self.inner.into_inner()?.into_inner()
}
}
impl<T, S> AsSubscriberSet for ReadSignal<T, S>
where
S: Storage<ArcReadSignal<T>>,
{
type Output = Arc<RwLock<SubscriberSet>>;
fn as_subscriber_set(&self) -> Option<Self::Output> {
self.inner
.try_with_value(|inner| inner.as_subscriber_set())
.flatten()
}
}
impl<T, S> ReadUntracked for ReadSignal<T, S>
where
T: 'static,
S: Storage<ArcReadSignal<T>>,
{
type Value = ReadGuard<T, Plain<T>>;
fn try_read_untracked(&self) -> Option<Self::Value> {
self.inner
.try_get_value()
.map(|inner| inner.read_untracked())
}
}
impl<T> From<ArcReadSignal<T>> for ReadSignal<T>
where
T: Send + Sync + 'static,
{
#[track_caller]
fn from(value: ArcReadSignal<T>) -> Self {
ReadSignal {
#[cfg(any(debug_assertions, leptos_debuginfo))]
defined_at: Location::caller(),
inner: ArenaItem::new_with_storage(value),
}
}
}
impl<T> FromLocal<ArcReadSignal<T>> for ReadSignal<T, LocalStorage>
where
T: 'static,
{
#[track_caller]
fn from_local(value: ArcReadSignal<T>) -> Self {
ReadSignal {
#[cfg(any(debug_assertions, leptos_debuginfo))]
defined_at: Location::caller(),
inner: ArenaItem::new_with_storage(value),
}
}
}
impl<T, S> From<ReadSignal<T, S>> for ArcReadSignal<T>
where
T: 'static,
S: Storage<ArcReadSignal<T>>,
{
#[track_caller]
fn from(value: ReadSignal<T, S>) -> Self {
value
.inner
.try_get_value()
.unwrap_or_else(unwrap_signal!(value))
}
}