reactive_graph/signal/
read.rs1use super::{
2 guards::{Plain, ReadGuard},
3 subscriber_traits::AsSubscriberSet,
4 ArcReadSignal,
5};
6use crate::{
7 graph::SubscriberSet,
8 owner::{ArenaItem, FromLocal, LocalStorage, Storage, SyncStorage},
9 traits::{DefinedAt, Dispose, IntoInner, IsDisposed, ReadUntracked},
10 unwrap_signal,
11};
12use core::fmt::Debug;
13use std::{
14 hash::Hash,
15 panic::Location,
16 sync::{Arc, RwLock},
17};
18
19pub struct ReadSignal<T, S = SyncStorage> {
61 #[cfg(any(debug_assertions, leptos_debuginfo))]
62 pub(crate) defined_at: &'static Location<'static>,
63 pub(crate) inner: ArenaItem<ArcReadSignal<T>, S>,
64}
65
66impl<T, S> Dispose for ReadSignal<T, S> {
67 fn dispose(self) {
68 self.inner.dispose()
69 }
70}
71
72impl<T, S> Copy for ReadSignal<T, S> {}
73
74impl<T, S> Clone for ReadSignal<T, S> {
75 fn clone(&self) -> Self {
76 *self
77 }
78}
79
80impl<T, S> Debug for ReadSignal<T, S>
81where
82 S: Debug,
83{
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 f.debug_struct("ReadSignal")
86 .field("type", &std::any::type_name::<T>())
87 .field("store", &self.inner)
88 .finish()
89 }
90}
91
92impl<T, S> PartialEq for ReadSignal<T, S> {
93 fn eq(&self, other: &Self) -> bool {
94 self.inner == other.inner
95 }
96}
97
98impl<T, S> Eq for ReadSignal<T, S> {}
99
100impl<T, S> Hash for ReadSignal<T, S> {
101 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
102 self.inner.hash(state);
103 }
104}
105
106impl<T, S> DefinedAt for ReadSignal<T, S> {
107 fn defined_at(&self) -> Option<&'static Location<'static>> {
108 #[cfg(any(debug_assertions, leptos_debuginfo))]
109 {
110 Some(self.defined_at)
111 }
112 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
113 {
114 None
115 }
116 }
117}
118
119impl<T, S> IsDisposed for ReadSignal<T, S> {
120 fn is_disposed(&self) -> bool {
121 self.inner.is_disposed()
122 }
123}
124
125impl<T, S> IntoInner for ReadSignal<T, S>
126where
127 S: Storage<ArcReadSignal<T>>,
128{
129 type Value = T;
130
131 #[inline(always)]
132 fn into_inner(self) -> Option<Self::Value> {
133 self.inner.into_inner()?.into_inner()
134 }
135}
136
137impl<T, S> AsSubscriberSet for ReadSignal<T, S>
138where
139 S: Storage<ArcReadSignal<T>>,
140{
141 type Output = Arc<RwLock<SubscriberSet>>;
142
143 fn as_subscriber_set(&self) -> Option<Self::Output> {
144 self.inner
145 .try_with_value(|inner| inner.as_subscriber_set())
146 .flatten()
147 }
148}
149
150impl<T, S> ReadUntracked for ReadSignal<T, S>
151where
152 T: 'static,
153 S: Storage<ArcReadSignal<T>>,
154{
155 type Value = ReadGuard<T, Plain<T>>;
156
157 fn try_read_untracked(&self) -> Option<Self::Value> {
158 self.inner
159 .try_get_value()
160 .map(|inner| inner.read_untracked())
161 }
162}
163
164impl<T> From<ArcReadSignal<T>> for ReadSignal<T>
165where
166 T: Send + Sync + 'static,
167{
168 #[track_caller]
169 fn from(value: ArcReadSignal<T>) -> Self {
170 ReadSignal {
171 #[cfg(any(debug_assertions, leptos_debuginfo))]
172 defined_at: Location::caller(),
173 inner: ArenaItem::new_with_storage(value),
174 }
175 }
176}
177
178impl<T> FromLocal<ArcReadSignal<T>> for ReadSignal<T, LocalStorage>
179where
180 T: 'static,
181{
182 #[track_caller]
183 fn from_local(value: ArcReadSignal<T>) -> Self {
184 ReadSignal {
185 #[cfg(any(debug_assertions, leptos_debuginfo))]
186 defined_at: Location::caller(),
187 inner: ArenaItem::new_with_storage(value),
188 }
189 }
190}
191
192impl<T, S> From<ReadSignal<T, S>> for ArcReadSignal<T>
193where
194 T: 'static,
195 S: Storage<ArcReadSignal<T>>,
196{
197 #[track_caller]
198 fn from(value: ReadSignal<T, S>) -> Self {
199 value
200 .inner
201 .try_get_value()
202 .unwrap_or_else(unwrap_signal!(value))
203 }
204}