1use super::{
2 arc_stored_value::ArcStoredValue, ArenaItem, LocalStorage, Storage,
3 SyncStorage,
4};
5use crate::{
6 signal::guards::{Plain, ReadGuard, UntrackedWriteGuard},
7 traits::{
8 DefinedAt, Dispose, IntoInner, IsDisposed, ReadValue, WriteValue,
9 },
10 unwrap_signal,
11};
12use std::{
13 fmt::{Debug, Formatter},
14 hash::Hash,
15 panic::Location,
16};
17
18pub struct StoredValue<T, S = SyncStorage> {
26 value: ArenaItem<ArcStoredValue<T>, S>,
27 #[cfg(any(debug_assertions, leptos_debuginfo))]
28 defined_at: &'static Location<'static>,
29}
30
31impl<T, S> Copy for StoredValue<T, S> {}
32
33impl<T, S> Clone for StoredValue<T, S> {
34 fn clone(&self) -> Self {
35 *self
36 }
37}
38
39impl<T, S> Debug for StoredValue<T, S>
40where
41 S: Debug,
42{
43 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
44 f.debug_struct("StoredValue")
45 .field("type", &std::any::type_name::<T>())
46 .field("value", &self.value)
47 .finish()
48 }
49}
50
51impl<T, S> PartialEq for StoredValue<T, S> {
52 fn eq(&self, other: &Self) -> bool {
53 self.value == other.value
54 }
55}
56
57impl<T, S> Eq for StoredValue<T, S> {}
58
59impl<T, S> Hash for StoredValue<T, S> {
60 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
61 self.value.hash(state);
62 }
63}
64
65impl<T, S> DefinedAt for StoredValue<T, S> {
66 fn defined_at(&self) -> Option<&'static Location<'static>> {
67 #[cfg(any(debug_assertions, leptos_debuginfo))]
68 {
69 Some(self.defined_at)
70 }
71 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
72 {
73 None
74 }
75 }
76}
77
78impl<T, S> StoredValue<T, S>
79where
80 T: 'static,
81 S: Storage<ArcStoredValue<T>>,
82{
83 #[track_caller]
85 pub fn new_with_storage(value: T) -> Self {
86 Self {
87 value: ArenaItem::new_with_storage(ArcStoredValue::new(value)),
88 #[cfg(any(debug_assertions, leptos_debuginfo))]
89 defined_at: Location::caller(),
90 }
91 }
92}
93
94impl<T, S> Default for StoredValue<T, S>
95where
96 T: Default + 'static,
97 S: Storage<ArcStoredValue<T>>,
98{
99 #[track_caller] fn default() -> Self {
101 Self::new_with_storage(Default::default())
102 }
103}
104
105impl<T> StoredValue<T>
106where
107 T: Send + Sync + 'static,
108{
109 #[track_caller]
111 pub fn new(value: T) -> Self {
112 StoredValue::new_with_storage(value)
113 }
114}
115
116impl<T> StoredValue<T, LocalStorage>
117where
118 T: 'static,
119{
120 #[track_caller]
122 pub fn new_local(value: T) -> Self {
123 StoredValue::new_with_storage(value)
124 }
125}
126
127impl<T, S> ReadValue for StoredValue<T, S>
128where
129 T: 'static,
130 S: Storage<ArcStoredValue<T>>,
131{
132 type Value = ReadGuard<T, Plain<T>>;
133
134 fn try_read_value(&self) -> Option<ReadGuard<T, Plain<T>>> {
135 self.value
136 .try_get_value()
137 .and_then(|inner| inner.try_read_value())
138 }
139}
140
141impl<T, S> WriteValue for StoredValue<T, S>
142where
143 T: 'static,
144 S: Storage<ArcStoredValue<T>>,
145{
146 type Value = T;
147
148 fn try_write_value(&self) -> Option<UntrackedWriteGuard<T>> {
149 self.value
150 .try_get_value()
151 .and_then(|inner| inner.try_write_value())
152 }
153}
154
155impl<T, S> IsDisposed for StoredValue<T, S> {
156 fn is_disposed(&self) -> bool {
157 self.value.is_disposed()
158 }
159}
160
161impl<T, S> Dispose for StoredValue<T, S> {
162 fn dispose(self) {
163 self.value.dispose();
164 }
165}
166
167impl<T, S> IntoInner for StoredValue<T, S>
168where
169 T: 'static,
170 S: Storage<ArcStoredValue<T>>,
171{
172 type Value = T;
173
174 #[inline(always)]
175 fn into_inner(self) -> Option<Self::Value> {
176 self.value.into_inner()?.into_inner()
177 }
178}
179
180impl<T> From<ArcStoredValue<T>> for StoredValue<T>
181where
182 T: Send + Sync + 'static,
183{
184 #[track_caller]
185 fn from(value: ArcStoredValue<T>) -> Self {
186 StoredValue {
187 #[cfg(any(debug_assertions, leptos_debuginfo))]
188 defined_at: Location::caller(),
189 value: ArenaItem::new(value),
190 }
191 }
192}
193
194impl<T, S> From<StoredValue<T, S>> for ArcStoredValue<T>
195where
196 S: Storage<ArcStoredValue<T>>,
197{
198 #[track_caller]
199 fn from(value: StoredValue<T, S>) -> Self {
200 value
201 .value
202 .try_get_value()
203 .unwrap_or_else(unwrap_signal!(value))
204 }
205}
206
207#[inline(always)]
209#[track_caller]
210#[deprecated(
211 since = "0.7.0-beta5",
212 note = "This function is being removed to conform to Rust idioms. Please \
213 use `StoredValue::new()` or `StoredValue::new_local()` instead."
214)]
215pub fn store_value<T>(value: T) -> StoredValue<T>
216where
217 T: Send + Sync + 'static,
218{
219 StoredValue::new(value)
220}
221
222pub trait FromLocal<T> {
227 fn from_local(value: T) -> Self;
229}