Skip to main content

reactive_graph/
wrappers.rs

1//! Types to abstract over different kinds of readable or writable reactive values.
2
3/// Types that abstract over signals with values that can be read.
4pub mod read {
5    use crate::{
6        computed::{ArcMemo, Memo},
7        graph::untrack,
8        owner::{
9            ArcStoredValue, ArenaItem, FromLocal, LocalStorage, Storage,
10            SyncStorage,
11        },
12        signal::{
13            guards::{Mapped, Plain, ReadGuard},
14            ArcMappedSignal, ArcReadSignal, ArcRwSignal, MappedSignal,
15            ReadSignal, RwSignal,
16        },
17        traits::{
18            DefinedAt, Dispose, Get, Read, ReadUntracked, ReadValue, Track,
19        },
20        unwrap_signal,
21    };
22    use send_wrapper::SendWrapper;
23    use std::{
24        borrow::Borrow,
25        fmt::Display,
26        ops::Deref,
27        panic::Location,
28        sync::{Arc, RwLock},
29    };
30
31    /// Possibilities for the inner type of a [`Signal`].
32    pub enum SignalTypes<T, S = SyncStorage>
33    where
34        S: Storage<T>,
35    {
36        /// A readable signal.
37        ReadSignal(ArcReadSignal<T>),
38        /// A memo.
39        Memo(ArcMemo<T, S>),
40        /// A derived signal.
41        DerivedSignal(Arc<dyn Fn() -> T + Send + Sync>),
42        /// A static, stored value.
43        Stored(ArcStoredValue<T>),
44    }
45
46    impl<T, S> Clone for SignalTypes<T, S>
47    where
48        S: Storage<T>,
49    {
50        fn clone(&self) -> Self {
51            match self {
52                Self::ReadSignal(arg0) => Self::ReadSignal(arg0.clone()),
53                Self::Memo(arg0) => Self::Memo(arg0.clone()),
54                Self::DerivedSignal(arg0) => Self::DerivedSignal(arg0.clone()),
55                Self::Stored(arg0) => Self::Stored(arg0.clone()),
56            }
57        }
58    }
59
60    impl<T, S> core::fmt::Debug for SignalTypes<T, S>
61    where
62        S: Storage<T>,
63    {
64        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65            match self {
66                Self::ReadSignal(arg0) => {
67                    f.debug_tuple("ReadSignal").field(arg0).finish()
68                }
69                Self::Memo(arg0) => f.debug_tuple("Memo").field(arg0).finish(),
70                Self::DerivedSignal(_) => {
71                    f.debug_tuple("DerivedSignal").finish()
72                }
73                Self::Stored(arg0) => {
74                    f.debug_tuple("Static").field(arg0).finish()
75                }
76            }
77        }
78    }
79
80    impl<T, S> PartialEq for SignalTypes<T, S>
81    where
82        S: Storage<T>,
83    {
84        fn eq(&self, other: &Self) -> bool {
85            match (self, other) {
86                (Self::ReadSignal(l0), Self::ReadSignal(r0)) => l0 == r0,
87                (Self::Memo(l0), Self::Memo(r0)) => l0 == r0,
88                (Self::DerivedSignal(l0), Self::DerivedSignal(r0)) => {
89                    std::ptr::eq(l0, r0)
90                }
91                _ => false,
92            }
93        }
94    }
95
96    /// A wrapper for any kind of reference-counted reactive signal:
97    /// an [`ArcReadSignal`], [`ArcMemo`], [`ArcRwSignal`], or derived signal closure,
98    /// or a plain value of the same type
99    ///
100    /// This allows you to create APIs that take `T` or any reactive value that returns `T`
101    /// as an argument, rather than adding a generic `F: Fn() -> T`.
102    ///
103    /// Values can be accessed with the same function call, `read()`, `with()`, and `get()`
104    /// APIs as other signals.
105    ///
106    /// ## Important Notes about Derived Signals
107    ///
108    /// `Signal::derive()` is simply a way to box and type-erase a “derived signal,” which
109    /// is a plain closure that accesses one or more signals. It does *not* cache the value
110    /// of that computation. Accessing the value of a `Signal<_>` that is created using `Signal::derive()`
111    /// will run the closure again every time you call `.read()`, `.with()`, or `.get()`.
112    ///
113    /// If you want the closure to run the minimal number of times necessary to update its state,
114    /// and then to cache its value, you should use a [`Memo`] (and convert it into a `Signal<_>`)
115    /// rather than using `Signal::derive()`.
116    ///
117    /// Note that for many computations, it is nevertheless less expensive to use a derived signal
118    /// than to create a separate memo and to cache the value: creating a new reactive node and
119    /// taking the lock on that cached value whenever you access the signal is *more* expensive than
120    /// simply re-running the calculation in many cases.
121    pub struct ArcSignal<T: 'static, S = SyncStorage>
122    where
123        S: Storage<T>,
124    {
125        #[cfg(any(debug_assertions, leptos_debuginfo))]
126        defined_at: &'static Location<'static>,
127        inner: SignalTypes<T, S>,
128    }
129
130    impl<T, S> Clone for ArcSignal<T, S>
131    where
132        S: Storage<T>,
133    {
134        fn clone(&self) -> Self {
135            Self {
136                #[cfg(any(debug_assertions, leptos_debuginfo))]
137                defined_at: self.defined_at,
138                inner: self.inner.clone(),
139            }
140        }
141    }
142
143    impl<T, S> core::fmt::Debug for ArcSignal<T, S>
144    where
145        S: Storage<T>,
146    {
147        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
148            let mut s = f.debug_struct("ArcSignal");
149            s.field("inner", &self.inner);
150            #[cfg(any(debug_assertions, leptos_debuginfo))]
151            s.field("defined_at", &self.defined_at);
152            s.finish()
153        }
154    }
155
156    impl<T, S> Eq for ArcSignal<T, S> where S: Storage<T> {}
157
158    impl<T, S> PartialEq for ArcSignal<T, S>
159    where
160        S: Storage<T>,
161    {
162        fn eq(&self, other: &Self) -> bool {
163            self.inner == other.inner
164        }
165    }
166
167    impl<T> ArcSignal<T, SyncStorage>
168    where
169        SyncStorage: Storage<T>,
170    {
171        /// Wraps a derived signal, i.e., any computation that accesses one or more
172        /// reactive signals.
173        /// ```rust
174        /// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
175        /// # use reactive_graph::wrappers::read::ArcSignal;
176        /// # use reactive_graph::prelude::*;
177        /// let (count, set_count) = arc_signal(2);
178        /// let double_count = ArcSignal::derive({
179        ///     let count = count.clone();
180        ///     move || count.get() * 2
181        /// });
182        ///
183        /// // this function takes any kind of wrapped signal
184        /// fn above_3(arg: &ArcSignal<i32>) -> bool {
185        ///     arg.get() > 3
186        /// }
187        ///
188        /// assert_eq!(above_3(&count.into()), false);
189        /// assert_eq!(above_3(&double_count), true);
190        /// ```
191        #[track_caller]
192        pub fn derive(
193            derived_signal: impl Fn() -> T + Send + Sync + 'static,
194        ) -> Self {
195            #[cfg(feature = "tracing")]
196            let span = ::tracing::Span::current();
197
198            let derived_signal = move || {
199                #[cfg(feature = "tracing")]
200                let _guard = span.enter();
201                derived_signal()
202            };
203
204            Self {
205                inner: SignalTypes::DerivedSignal(Arc::new(derived_signal)),
206                #[cfg(any(debug_assertions, leptos_debuginfo))]
207                defined_at: std::panic::Location::caller(),
208            }
209        }
210
211        /// Moves a static, nonreactive value into a signal, backed by [`ArcStoredValue`].
212        #[track_caller]
213        pub fn stored(value: T) -> Self {
214            Self {
215                inner: SignalTypes::Stored(ArcStoredValue::new(value)),
216                #[cfg(any(debug_assertions, leptos_debuginfo))]
217                defined_at: std::panic::Location::caller(),
218            }
219        }
220    }
221
222    impl<T> ArcSignal<T, LocalStorage>
223    where
224        T: 'static,
225    {
226        /// Wraps a derived signal. Works like [`Signal::derive`] but uses [`LocalStorage`].
227        #[track_caller]
228        pub fn derive_local(derived_signal: impl Fn() -> T + 'static) -> Self {
229            Signal::derive_local(derived_signal).into()
230        }
231
232        /// Moves a static, nonreactive value into a signal, backed by [`ArcStoredValue`].
233        /// Works like [`Signal::stored`] but uses [`LocalStorage`].
234        #[track_caller]
235        pub fn stored_local(value: T) -> Self {
236            Signal::stored_local(value).into()
237        }
238    }
239
240    impl<T> Default for ArcSignal<T, SyncStorage>
241    where
242        T: Default + Send + Sync + 'static,
243    {
244        fn default() -> Self {
245            Self::stored(Default::default())
246        }
247    }
248
249    impl<T: Send + Sync> From<ArcReadSignal<T>> for ArcSignal<T, SyncStorage> {
250        #[track_caller]
251        fn from(value: ArcReadSignal<T>) -> Self {
252            Self {
253                inner: SignalTypes::ReadSignal(value),
254                #[cfg(any(debug_assertions, leptos_debuginfo))]
255                defined_at: std::panic::Location::caller(),
256            }
257        }
258    }
259
260    impl<T, S> From<ReadSignal<T, S>> for ArcSignal<T, S>
261    where
262        S: Storage<ArcReadSignal<T>> + Storage<T>,
263    {
264        #[track_caller]
265        fn from(value: ReadSignal<T, S>) -> Self {
266            Self {
267                inner: SignalTypes::ReadSignal(value.into()),
268                #[cfg(any(debug_assertions, leptos_debuginfo))]
269                defined_at: std::panic::Location::caller(),
270            }
271        }
272    }
273
274    impl<T: Send + Sync> From<ArcRwSignal<T>> for ArcSignal<T, SyncStorage> {
275        #[track_caller]
276        fn from(value: ArcRwSignal<T>) -> Self {
277            Self {
278                inner: SignalTypes::ReadSignal(value.read_only()),
279                #[cfg(any(debug_assertions, leptos_debuginfo))]
280                defined_at: std::panic::Location::caller(),
281            }
282        }
283    }
284
285    impl<T, S> From<RwSignal<T, S>> for ArcSignal<T, S>
286    where
287        S: Storage<ArcRwSignal<T>> + Storage<ArcReadSignal<T>> + Storage<T>,
288    {
289        #[track_caller]
290        fn from(value: RwSignal<T, S>) -> Self {
291            Self {
292                inner: SignalTypes::ReadSignal(value.read_only().into()),
293                #[cfg(any(debug_assertions, leptos_debuginfo))]
294                defined_at: std::panic::Location::caller(),
295            }
296        }
297    }
298
299    impl<T, S> From<ArcMemo<T, S>> for ArcSignal<T, S>
300    where
301        S: Storage<T>,
302    {
303        #[track_caller]
304        fn from(value: ArcMemo<T, S>) -> Self {
305            Self {
306                inner: SignalTypes::Memo(value),
307                #[cfg(any(debug_assertions, leptos_debuginfo))]
308                defined_at: std::panic::Location::caller(),
309            }
310        }
311    }
312
313    impl<T, S> From<Memo<T, S>> for ArcSignal<T, S>
314    where
315        S: Storage<ArcMemo<T, S>> + Storage<T>,
316    {
317        #[track_caller]
318        fn from(value: Memo<T, S>) -> Self {
319            Self {
320                inner: SignalTypes::Memo(value.into()),
321                #[cfg(any(debug_assertions, leptos_debuginfo))]
322                defined_at: std::panic::Location::caller(),
323            }
324        }
325    }
326
327    impl<S> From<&'static str> for ArcSignal<String, S>
328    where
329        S: Storage<&'static str> + Storage<String>,
330    {
331        #[track_caller]
332        fn from(value: &'static str) -> Self {
333            Self {
334                inner: SignalTypes::Stored(ArcStoredValue::new(
335                    value.to_string(),
336                )),
337                #[cfg(any(debug_assertions, leptos_debuginfo))]
338                defined_at: std::panic::Location::caller(),
339            }
340        }
341    }
342
343    impl<T, S> DefinedAt for ArcSignal<T, S>
344    where
345        S: Storage<T>,
346    {
347        fn defined_at(&self) -> Option<&'static Location<'static>> {
348            #[cfg(any(debug_assertions, leptos_debuginfo))]
349            {
350                Some(self.defined_at)
351            }
352            #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
353            {
354                None
355            }
356        }
357    }
358
359    impl<T, S> Track for ArcSignal<T, S>
360    where
361        S: Storage<T>,
362    {
363        fn track(&self) {
364            match &self.inner {
365                SignalTypes::ReadSignal(i) => {
366                    i.track();
367                }
368                SignalTypes::Memo(i) => {
369                    i.track();
370                }
371                SignalTypes::DerivedSignal(i) => {
372                    i();
373                }
374                // Doesn't change.
375                SignalTypes::Stored(_) => {}
376            }
377        }
378    }
379
380    impl<T, S> ReadUntracked for ArcSignal<T, S>
381    where
382        S: Storage<T>,
383    {
384        type Value = ReadGuard<T, SignalReadGuard<T, S>>;
385
386        fn try_read_untracked(&self) -> Option<Self::Value> {
387            match &self.inner {
388                SignalTypes::ReadSignal(i) => {
389                    i.try_read_untracked().map(SignalReadGuard::Read)
390                }
391                SignalTypes::Memo(i) => {
392                    i.try_read_untracked().map(SignalReadGuard::Memo)
393                }
394                SignalTypes::DerivedSignal(i) => {
395                    Some(SignalReadGuard::Owned(untrack(|| i())))
396                }
397                SignalTypes::Stored(i) => {
398                    i.try_read_value().map(SignalReadGuard::Read)
399                }
400            }
401            .map(ReadGuard::new)
402        }
403
404        /// Overriding the default auto implemented [`Read::try_read`] to combine read and track,
405        /// to avoid 2 clones and just have 1 in the [`SignalTypes::DerivedSignal`].
406        fn custom_try_read(&self) -> Option<Option<Self::Value>> {
407            Some(
408                match &self.inner {
409                    SignalTypes::ReadSignal(i) => {
410                        i.try_read().map(SignalReadGuard::Read)
411                    }
412                    SignalTypes::Memo(i) => {
413                        i.try_read().map(SignalReadGuard::Memo)
414                    }
415                    SignalTypes::DerivedSignal(i) => {
416                        Some(SignalReadGuard::Owned(i()))
417                    }
418                    SignalTypes::Stored(i) => {
419                        i.try_read_value().map(SignalReadGuard::Read)
420                    }
421                }
422                .map(ReadGuard::new),
423            )
424        }
425    }
426
427    /// A wrapper for any kind of arena-allocated reactive signal:
428    /// a [`ReadSignal`], [`Memo`], [`RwSignal`], or derived signal closure,
429    /// or a plain value of the same type
430    ///
431    /// This allows you to create APIs that take `T` or any reactive value that returns `T`
432    /// as an argument, rather than adding a generic `F: Fn() -> T`.
433    ///
434    /// Values can be accessed with the same function call, `read()`, `with()`, and `get()`
435    /// APIs as other signals.
436    ///
437    /// ## Important Notes about Derived Signals
438    ///
439    /// `Signal::derive()` is simply a way to box and type-erase a “derived signal,” which
440    /// is a plain closure that accesses one or more signals. It does *not* cache the value
441    /// of that computation. Accessing the value of a `Signal<_>` that is created using `Signal::derive()`
442    /// will run the closure again every time you call `.read()`, `.with()`, or `.get()`.
443    ///
444    /// If you want the closure to run the minimal number of times necessary to update its state,
445    /// and then to cache its value, you should use a [`Memo`] (and convert it into a `Signal<_>`)
446    /// rather than using `Signal::derive()`.
447    ///
448    /// Note that for many computations, it is nevertheless less expensive to use a derived signal
449    /// than to create a separate memo and to cache the value: creating a new reactive node and
450    /// taking the lock on that cached value whenever you access the signal is *more* expensive than
451    /// simply re-running the calculation in many cases.
452    pub struct Signal<T, S = SyncStorage>
453    where
454        S: Storage<T>,
455    {
456        #[cfg(any(debug_assertions, leptos_debuginfo))]
457        defined_at: &'static Location<'static>,
458        inner: ArenaItem<SignalTypes<T, S>, S>,
459    }
460
461    impl<T, S> Dispose for Signal<T, S>
462    where
463        S: Storage<T>,
464    {
465        fn dispose(self) {
466            self.inner.dispose()
467        }
468    }
469
470    impl<T, S> Clone for Signal<T, S>
471    where
472        S: Storage<T>,
473    {
474        fn clone(&self) -> Self {
475            *self
476        }
477    }
478
479    impl<T, S> Copy for Signal<T, S> where S: Storage<T> {}
480
481    impl<T, S> core::fmt::Debug for Signal<T, S>
482    where
483        S: std::fmt::Debug + Storage<T>,
484    {
485        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
486            let mut s = f.debug_struct("Signal");
487            s.field("inner", &self.inner);
488            #[cfg(any(debug_assertions, leptos_debuginfo))]
489            s.field("defined_at", &self.defined_at);
490            s.finish()
491        }
492    }
493
494    impl<T, S> Eq for Signal<T, S> where S: Storage<T> {}
495
496    impl<T, S> PartialEq for Signal<T, S>
497    where
498        S: Storage<T>,
499    {
500        fn eq(&self, other: &Self) -> bool {
501            self.inner == other.inner
502        }
503    }
504
505    impl<T, S> DefinedAt for Signal<T, S>
506    where
507        S: Storage<T>,
508    {
509        fn defined_at(&self) -> Option<&'static Location<'static>> {
510            #[cfg(any(debug_assertions, leptos_debuginfo))]
511            {
512                Some(self.defined_at)
513            }
514            #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
515            {
516                None
517            }
518        }
519    }
520
521    impl<T, S> Track for Signal<T, S>
522    where
523        T: 'static,
524        S: Storage<T> + Storage<SignalTypes<T, S>>,
525    {
526        fn track(&self) {
527            let inner = self
528                .inner
529                // clone the inner Arc type and release the lock
530                // prevents deadlocking if the derived value includes taking a lock on the arena
531                .try_with_value(Clone::clone)
532                .unwrap_or_else(unwrap_signal!(self));
533            match inner {
534                SignalTypes::ReadSignal(i) => {
535                    i.track();
536                }
537                SignalTypes::Memo(i) => {
538                    i.track();
539                }
540                SignalTypes::DerivedSignal(i) => {
541                    i();
542                }
543                // Doesn't change.
544                SignalTypes::Stored(_) => {}
545            }
546        }
547    }
548
549    impl<T, S> ReadUntracked for Signal<T, S>
550    where
551        T: 'static,
552        S: Storage<SignalTypes<T, S>> + Storage<T>,
553    {
554        type Value = ReadGuard<T, SignalReadGuard<T, S>>;
555
556        fn try_read_untracked(&self) -> Option<Self::Value> {
557            self.inner
558                // clone the inner Arc type and release the lock
559                // prevents deadlocking if the derived value includes taking a lock on the arena
560                .try_with_value(Clone::clone)
561                .and_then(|inner| {
562                    match &inner {
563                        SignalTypes::ReadSignal(i) => {
564                            i.try_read_untracked().map(SignalReadGuard::Read)
565                        }
566                        SignalTypes::Memo(i) => {
567                            i.try_read_untracked().map(SignalReadGuard::Memo)
568                        }
569                        SignalTypes::DerivedSignal(i) => {
570                            Some(SignalReadGuard::Owned(untrack(|| i())))
571                        }
572                        SignalTypes::Stored(i) => {
573                            i.try_read_value().map(SignalReadGuard::Read)
574                        }
575                    }
576                    .map(ReadGuard::new)
577                })
578        }
579
580        /// Overriding the default auto implemented [`Read::try_read`] to combine read and track,
581        /// to avoid 2 clones and just have 1 in the [`SignalTypes::DerivedSignal`].
582        fn custom_try_read(&self) -> Option<Option<Self::Value>> {
583            Some(
584                self.inner
585                    // clone the inner Arc type and release the lock
586                    // prevents deadlocking if the derived value includes taking a lock on the arena
587                    .try_with_value(Clone::clone)
588                    .and_then(|inner| {
589                        match &inner {
590                            SignalTypes::ReadSignal(i) => {
591                                i.try_read().map(SignalReadGuard::Read)
592                            }
593                            SignalTypes::Memo(i) => {
594                                i.try_read().map(SignalReadGuard::Memo)
595                            }
596                            SignalTypes::DerivedSignal(i) => {
597                                Some(SignalReadGuard::Owned(i()))
598                            }
599                            SignalTypes::Stored(i) => {
600                                i.try_read_value().map(SignalReadGuard::Read)
601                            }
602                        }
603                        .map(ReadGuard::new)
604                    }),
605            )
606        }
607    }
608
609    impl<T> Signal<T>
610    where
611        T: Send + Sync + 'static,
612    {
613        /// Wraps a derived signal, i.e., any computation that accesses one or more
614        /// reactive signals.
615        /// ```rust
616        /// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
617        /// # use reactive_graph::wrappers::read::Signal;
618        /// # use reactive_graph::prelude::*;
619        /// let (count, set_count) = signal(2);
620        /// let double_count = Signal::derive(move || count.get() * 2);
621        ///
622        /// // this function takes any kind of wrapped signal
623        /// fn above_3(arg: &Signal<i32>) -> bool {
624        ///     arg.get() > 3
625        /// }
626        ///
627        /// assert_eq!(above_3(&count.into()), false);
628        /// assert_eq!(above_3(&double_count), true);
629        /// ```
630        #[track_caller]
631        pub fn derive(
632            derived_signal: impl Fn() -> T + Send + Sync + 'static,
633        ) -> Self {
634            #[cfg(feature = "tracing")]
635            let span = ::tracing::Span::current();
636
637            let derived_signal = move || {
638                #[cfg(feature = "tracing")]
639                let _guard = span.enter();
640                derived_signal()
641            };
642
643            Self {
644                inner: ArenaItem::new_with_storage(SignalTypes::DerivedSignal(
645                    Arc::new(derived_signal),
646                )),
647                #[cfg(any(debug_assertions, leptos_debuginfo))]
648                defined_at: std::panic::Location::caller(),
649            }
650        }
651
652        /// Moves a static, nonreactive value into a signal, backed by [`ArcStoredValue`].
653        #[track_caller]
654        pub fn stored(value: T) -> Self {
655            Self {
656                inner: ArenaItem::new_with_storage(SignalTypes::Stored(
657                    ArcStoredValue::new(value),
658                )),
659                #[cfg(any(debug_assertions, leptos_debuginfo))]
660                defined_at: std::panic::Location::caller(),
661            }
662        }
663    }
664
665    impl<T> Signal<T, LocalStorage>
666    where
667        T: 'static,
668    {
669        /// Wraps a derived signal. Works like [`Signal::derive`] but uses [`LocalStorage`].
670        #[track_caller]
671        pub fn derive_local(derived_signal: impl Fn() -> T + 'static) -> Self {
672            let derived_signal = SendWrapper::new(derived_signal);
673            #[cfg(feature = "tracing")]
674            let span = ::tracing::Span::current();
675
676            let derived_signal = move || {
677                #[cfg(feature = "tracing")]
678                let _guard = span.enter();
679                derived_signal()
680            };
681
682            Self {
683                inner: ArenaItem::new_local(SignalTypes::DerivedSignal(
684                    Arc::new(derived_signal),
685                )),
686                #[cfg(any(debug_assertions, leptos_debuginfo))]
687                defined_at: std::panic::Location::caller(),
688            }
689        }
690
691        /// Moves a static, nonreactive value into a signal, backed by [`ArcStoredValue`].
692        /// Works like [`Signal::stored`] but uses [`LocalStorage`].
693        #[track_caller]
694        pub fn stored_local(value: T) -> Self {
695            Self {
696                inner: ArenaItem::new_local(SignalTypes::Stored(
697                    ArcStoredValue::new(value),
698                )),
699                #[cfg(any(debug_assertions, leptos_debuginfo))]
700                defined_at: std::panic::Location::caller(),
701            }
702        }
703    }
704
705    impl<T> Default for Signal<T>
706    where
707        T: Send + Sync + Default + 'static,
708    {
709        fn default() -> Self {
710            Self::stored(Default::default())
711        }
712    }
713
714    impl<T> Default for Signal<T, LocalStorage>
715    where
716        T: Default + 'static,
717    {
718        fn default() -> Self {
719            Self::stored_local(Default::default())
720        }
721    }
722
723    impl<T: Send + Sync + 'static> From<T> for ArcSignal<T, SyncStorage> {
724        #[track_caller]
725        fn from(value: T) -> Self {
726            ArcSignal::stored(value)
727        }
728    }
729
730    impl<T> From<T> for Signal<T>
731    where
732        T: Send + Sync + 'static,
733    {
734        #[track_caller]
735        fn from(value: T) -> Self {
736            Self::stored(value)
737        }
738    }
739
740    impl<T> From<T> for Signal<T, LocalStorage>
741    where
742        T: 'static,
743    {
744        #[track_caller]
745        fn from(value: T) -> Self {
746            Self::stored_local(value)
747        }
748    }
749
750    impl<T> From<ArcSignal<T, SyncStorage>> for Signal<T>
751    where
752        T: Send + Sync + 'static,
753    {
754        #[track_caller]
755        fn from(value: ArcSignal<T, SyncStorage>) -> Self {
756            Signal {
757                #[cfg(any(debug_assertions, leptos_debuginfo))]
758                defined_at: Location::caller(),
759                inner: ArenaItem::new(value.inner),
760            }
761        }
762    }
763
764    impl<T> FromLocal<ArcSignal<T, LocalStorage>> for Signal<T, LocalStorage>
765    where
766        T: 'static,
767    {
768        #[track_caller]
769        fn from_local(value: ArcSignal<T, LocalStorage>) -> Self {
770            Signal {
771                #[cfg(any(debug_assertions, leptos_debuginfo))]
772                defined_at: Location::caller(),
773                inner: ArenaItem::new_local(value.inner),
774            }
775        }
776    }
777
778    impl<T, S> From<Signal<T, S>> for ArcSignal<T, S>
779    where
780        S: Storage<SignalTypes<T, S>> + Storage<T>,
781    {
782        #[track_caller]
783        fn from(value: Signal<T, S>) -> Self {
784            ArcSignal {
785                #[cfg(any(debug_assertions, leptos_debuginfo))]
786                defined_at: Location::caller(),
787                inner: value
788                    .inner
789                    .try_get_value()
790                    .unwrap_or_else(unwrap_signal!(value)),
791            }
792        }
793    }
794
795    impl<T> From<ReadSignal<T>> for Signal<T>
796    where
797        T: Send + Sync + 'static,
798    {
799        #[track_caller]
800        fn from(value: ReadSignal<T>) -> Self {
801            Self {
802                inner: ArenaItem::new(SignalTypes::ReadSignal(value.into())),
803                #[cfg(any(debug_assertions, leptos_debuginfo))]
804                defined_at: std::panic::Location::caller(),
805            }
806        }
807    }
808
809    impl<T> From<ReadSignal<T, LocalStorage>> for Signal<T, LocalStorage>
810    where
811        T: 'static,
812    {
813        #[track_caller]
814        fn from(value: ReadSignal<T, LocalStorage>) -> Self {
815            Self {
816                inner: ArenaItem::new_local(SignalTypes::ReadSignal(
817                    value.into(),
818                )),
819                #[cfg(any(debug_assertions, leptos_debuginfo))]
820                defined_at: std::panic::Location::caller(),
821            }
822        }
823    }
824
825    impl<T> From<ArcReadSignal<T>> for Signal<T>
826    where
827        T: Send + Sync + 'static,
828    {
829        #[track_caller]
830        fn from(value: ArcReadSignal<T>) -> Self {
831            Self {
832                inner: ArenaItem::new(SignalTypes::ReadSignal(value)),
833                #[cfg(any(debug_assertions, leptos_debuginfo))]
834                defined_at: std::panic::Location::caller(),
835            }
836        }
837    }
838
839    impl<T> From<ArcReadSignal<T>> for Signal<T, LocalStorage>
840    where
841        T: Send + Sync + 'static,
842    {
843        #[track_caller]
844        fn from(value: ArcReadSignal<T>) -> Self {
845            Self {
846                inner: ArenaItem::new_local(SignalTypes::ReadSignal(value)),
847                #[cfg(any(debug_assertions, leptos_debuginfo))]
848                defined_at: std::panic::Location::caller(),
849            }
850        }
851    }
852
853    impl<T> From<RwSignal<T>> for Signal<T>
854    where
855        T: Send + Sync + 'static,
856    {
857        #[track_caller]
858        fn from(value: RwSignal<T>) -> Self {
859            Self {
860                inner: ArenaItem::new(SignalTypes::ReadSignal(
861                    value.read_only().into(),
862                )),
863                #[cfg(any(debug_assertions, leptos_debuginfo))]
864                defined_at: std::panic::Location::caller(),
865            }
866        }
867    }
868
869    impl<T> From<MappedSignal<T>> for Signal<T>
870    where
871        T: Clone + Send + Sync + 'static,
872    {
873        #[track_caller]
874        fn from(value: MappedSignal<T>) -> Self {
875            Self::derive(move || value.get())
876        }
877    }
878
879    impl<T> From<RwSignal<T, LocalStorage>> for Signal<T, LocalStorage>
880    where
881        T: 'static,
882    {
883        #[track_caller]
884        fn from(value: RwSignal<T, LocalStorage>) -> Self {
885            Self {
886                inner: ArenaItem::new_local(SignalTypes::ReadSignal(
887                    value.read_only().into(),
888                )),
889                #[cfg(any(debug_assertions, leptos_debuginfo))]
890                defined_at: std::panic::Location::caller(),
891            }
892        }
893    }
894
895    impl<T> From<ArcRwSignal<T>> for Signal<T>
896    where
897        T: Send + Sync + 'static,
898    {
899        #[track_caller]
900        fn from(value: ArcRwSignal<T>) -> Self {
901            Self {
902                inner: ArenaItem::new(SignalTypes::ReadSignal(
903                    value.read_only(),
904                )),
905                #[cfg(any(debug_assertions, leptos_debuginfo))]
906                defined_at: std::panic::Location::caller(),
907            }
908        }
909    }
910
911    impl<T> From<ArcMappedSignal<T>> for Signal<T>
912    where
913        T: Clone + Send + Sync + 'static,
914    {
915        #[track_caller]
916        fn from(value: ArcMappedSignal<T>) -> Self {
917            MappedSignal::from(value).into()
918        }
919    }
920
921    impl<T> From<ArcRwSignal<T>> for Signal<T, LocalStorage>
922    where
923        T: Send + Sync + 'static,
924    {
925        #[track_caller]
926        fn from(value: ArcRwSignal<T>) -> Self {
927            Self {
928                inner: ArenaItem::new_local(SignalTypes::ReadSignal(
929                    value.read_only(),
930                )),
931                #[cfg(any(debug_assertions, leptos_debuginfo))]
932                defined_at: std::panic::Location::caller(),
933            }
934        }
935    }
936
937    impl<T> From<Memo<T>> for Signal<T>
938    where
939        T: Send + Sync + 'static,
940    {
941        #[track_caller]
942        fn from(value: Memo<T>) -> Self {
943            Self {
944                inner: ArenaItem::new(SignalTypes::Memo(value.into())),
945                #[cfg(any(debug_assertions, leptos_debuginfo))]
946                defined_at: std::panic::Location::caller(),
947            }
948        }
949    }
950
951    impl<T> From<Memo<T, LocalStorage>> for Signal<T, LocalStorage>
952    where
953        T: 'static,
954    {
955        #[track_caller]
956        fn from(value: Memo<T, LocalStorage>) -> Self {
957            Self {
958                inner: ArenaItem::new_local(SignalTypes::Memo(value.into())),
959                #[cfg(any(debug_assertions, leptos_debuginfo))]
960                defined_at: std::panic::Location::caller(),
961            }
962        }
963    }
964
965    impl<T> From<ArcMemo<T>> for Signal<T>
966    where
967        T: Send + Sync + 'static,
968    {
969        #[track_caller]
970        fn from(value: ArcMemo<T>) -> Self {
971            Self {
972                inner: ArenaItem::new(SignalTypes::Memo(value)),
973                #[cfg(any(debug_assertions, leptos_debuginfo))]
974                defined_at: std::panic::Location::caller(),
975            }
976        }
977    }
978
979    impl<T> From<ArcMemo<T, LocalStorage>> for Signal<T, LocalStorage>
980    where
981        T: Send + Sync + 'static,
982    {
983        #[track_caller]
984        fn from(value: ArcMemo<T, LocalStorage>) -> Self {
985            Self {
986                inner: ArenaItem::new_local(SignalTypes::Memo(value)),
987                #[cfg(any(debug_assertions, leptos_debuginfo))]
988                defined_at: std::panic::Location::caller(),
989            }
990        }
991    }
992
993    impl<T> From<T> for Signal<Option<T>>
994    where
995        T: Send + Sync + 'static,
996    {
997        #[track_caller]
998        fn from(value: T) -> Self {
999            Signal::stored(Some(value))
1000        }
1001    }
1002
1003    impl<T> From<T> for Signal<Option<T>, LocalStorage>
1004    where
1005        T: 'static,
1006    {
1007        #[track_caller]
1008        fn from(value: T) -> Self {
1009            Signal::stored_local(Some(value))
1010        }
1011    }
1012
1013    impl<T> From<Signal<T>> for Signal<Option<T>>
1014    where
1015        T: Clone + Send + Sync + 'static,
1016    {
1017        #[track_caller]
1018        fn from(value: Signal<T>) -> Self {
1019            Signal::derive(move || Some(value.get()))
1020        }
1021    }
1022
1023    impl<T> From<Signal<T, LocalStorage>> for Signal<Option<T>, LocalStorage>
1024    where
1025        T: Clone + 'static,
1026    {
1027        #[track_caller]
1028        fn from(value: Signal<T, LocalStorage>) -> Self {
1029            Signal::derive_local(move || Some(value.get()))
1030        }
1031    }
1032
1033    impl From<&str> for Signal<String> {
1034        #[track_caller]
1035        fn from(value: &str) -> Self {
1036            Signal::stored(value.to_string())
1037        }
1038    }
1039
1040    impl From<&str> for Signal<String, LocalStorage> {
1041        #[track_caller]
1042        fn from(value: &str) -> Self {
1043            Signal::stored_local(value.to_string())
1044        }
1045    }
1046
1047    impl From<&str> for Signal<Option<String>> {
1048        #[track_caller]
1049        fn from(value: &str) -> Self {
1050            Signal::stored(Some(value.to_string()))
1051        }
1052    }
1053
1054    impl From<&str> for Signal<Option<String>, LocalStorage> {
1055        #[track_caller]
1056        fn from(value: &str) -> Self {
1057            Signal::stored_local(Some(value.to_string()))
1058        }
1059    }
1060
1061    impl From<Signal<&'static str>> for Signal<String> {
1062        #[track_caller]
1063        fn from(value: Signal<&'static str>) -> Self {
1064            Signal::derive(move || value.read().to_string())
1065        }
1066    }
1067
1068    impl From<Signal<&'static str, LocalStorage>> for Signal<String, LocalStorage> {
1069        #[track_caller]
1070        fn from(value: Signal<&'static str, LocalStorage>) -> Self {
1071            Signal::derive_local(move || value.read().to_string())
1072        }
1073    }
1074
1075    impl From<Signal<&'static str>> for Signal<String, LocalStorage> {
1076        #[track_caller]
1077        fn from(value: Signal<&'static str>) -> Self {
1078            Signal::derive_local(move || value.read().to_string())
1079        }
1080    }
1081
1082    impl From<Signal<&'static str>> for Signal<Option<String>> {
1083        #[track_caller]
1084        fn from(value: Signal<&'static str>) -> Self {
1085            Signal::derive(move || Some(value.read().to_string()))
1086        }
1087    }
1088
1089    impl From<Signal<&'static str>> for Signal<Option<String>, LocalStorage> {
1090        #[track_caller]
1091        fn from(value: Signal<&'static str>) -> Self {
1092            Signal::derive_local(move || Some(value.read().to_string()))
1093        }
1094    }
1095
1096    impl From<Signal<Option<&'static str>>> for Signal<Option<String>> {
1097        #[track_caller]
1098        fn from(value: Signal<Option<&'static str>>) -> Self {
1099            Signal::derive(move || value.read().map(str::to_string))
1100        }
1101    }
1102
1103    impl From<Signal<Option<&'static str>, LocalStorage>>
1104        for Signal<Option<String>, LocalStorage>
1105    {
1106        #[track_caller]
1107        fn from(value: Signal<Option<&'static str>, LocalStorage>) -> Self {
1108            Signal::derive_local(move || value.read().map(str::to_string))
1109        }
1110    }
1111
1112    impl From<Signal<Option<&'static str>>>
1113        for Signal<Option<String>, LocalStorage>
1114    {
1115        #[track_caller]
1116        fn from(value: Signal<Option<&'static str>>) -> Self {
1117            Signal::derive_local(move || value.read().map(str::to_string))
1118        }
1119    }
1120
1121    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1122    #[doc(hidden)]
1123    pub struct __IntoReactiveValueMarkerSignalFromReactiveClosure;
1124    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1125    #[doc(hidden)]
1126    pub struct __IntoReactiveValueMarkerSignalStrOutputToString;
1127    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1128    #[doc(hidden)]
1129    pub struct __IntoReactiveValueMarkerOptionalSignalFromReactiveClosureAlways;
1130
1131    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1132    impl<T, F>
1133        crate::IntoReactiveValue<
1134            Signal<T, SyncStorage>,
1135            __IntoReactiveValueMarkerSignalFromReactiveClosure,
1136        > for F
1137    where
1138        T: Send + Sync + 'static,
1139        F: Fn() -> T + Send + Sync + 'static,
1140    {
1141        fn into_reactive_value(self) -> Signal<T, SyncStorage> {
1142            Signal::derive(self)
1143        }
1144    }
1145
1146    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1147    impl<T, F>
1148        crate::IntoReactiveValue<
1149            ArcSignal<T, SyncStorage>,
1150            __IntoReactiveValueMarkerSignalFromReactiveClosure,
1151        > for F
1152    where
1153        T: Send + Sync + 'static,
1154        F: Fn() -> T + Send + Sync + 'static,
1155    {
1156        fn into_reactive_value(self) -> ArcSignal<T, SyncStorage> {
1157            ArcSignal::derive(self)
1158        }
1159    }
1160
1161    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1162    impl<T, F>
1163        crate::IntoReactiveValue<
1164            Signal<T, LocalStorage>,
1165            __IntoReactiveValueMarkerSignalFromReactiveClosure,
1166        > for F
1167    where
1168        T: 'static,
1169        F: Fn() -> T + 'static,
1170    {
1171        fn into_reactive_value(self) -> Signal<T, LocalStorage> {
1172            Signal::derive_local(self)
1173        }
1174    }
1175
1176    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1177    impl<T, F>
1178        crate::IntoReactiveValue<
1179            ArcSignal<T, LocalStorage>,
1180            __IntoReactiveValueMarkerSignalFromReactiveClosure,
1181        > for F
1182    where
1183        T: 'static,
1184        F: Fn() -> T + 'static,
1185    {
1186        fn into_reactive_value(self) -> ArcSignal<T, LocalStorage> {
1187            ArcSignal::derive_local(self)
1188        }
1189    }
1190
1191    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1192    impl<F>
1193        crate::IntoReactiveValue<
1194            Signal<String, SyncStorage>,
1195            __IntoReactiveValueMarkerSignalStrOutputToString,
1196        > for F
1197    where
1198        F: Fn() -> &'static str + Send + Sync + 'static,
1199    {
1200        fn into_reactive_value(self) -> Signal<String, SyncStorage> {
1201            Signal::derive(move || self().to_string())
1202        }
1203    }
1204
1205    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1206    impl<F>
1207        crate::IntoReactiveValue<
1208            ArcSignal<String, SyncStorage>,
1209            __IntoReactiveValueMarkerSignalStrOutputToString,
1210        > for F
1211    where
1212        F: Fn() -> &'static str + Send + Sync + 'static,
1213    {
1214        fn into_reactive_value(self) -> ArcSignal<String, SyncStorage> {
1215            ArcSignal::derive(move || self().to_string())
1216        }
1217    }
1218
1219    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1220    impl<F>
1221        crate::IntoReactiveValue<
1222            Signal<String, LocalStorage>,
1223            __IntoReactiveValueMarkerSignalStrOutputToString,
1224        > for F
1225    where
1226        F: Fn() -> &'static str + 'static,
1227    {
1228        fn into_reactive_value(self) -> Signal<String, LocalStorage> {
1229            Signal::derive_local(move || self().to_string())
1230        }
1231    }
1232
1233    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1234    impl<F>
1235        crate::IntoReactiveValue<
1236            ArcSignal<String, LocalStorage>,
1237            __IntoReactiveValueMarkerSignalStrOutputToString,
1238        > for F
1239    where
1240        F: Fn() -> &'static str + 'static,
1241    {
1242        fn into_reactive_value(self) -> ArcSignal<String, LocalStorage> {
1243            ArcSignal::derive_local(move || self().to_string())
1244        }
1245    }
1246
1247    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1248    impl<T, F>
1249        crate::IntoReactiveValue<
1250            Signal<Option<T>, SyncStorage>,
1251            __IntoReactiveValueMarkerOptionalSignalFromReactiveClosureAlways,
1252        > for F
1253    where
1254        T: Send + Sync + 'static,
1255        F: Fn() -> T + Send + Sync + 'static,
1256    {
1257        fn into_reactive_value(self) -> Signal<Option<T>, SyncStorage> {
1258            Signal::derive(move || Some(self()))
1259        }
1260    }
1261
1262    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1263    impl<T, F>
1264        crate::IntoReactiveValue<
1265            ArcSignal<Option<T>, SyncStorage>,
1266            __IntoReactiveValueMarkerOptionalSignalFromReactiveClosureAlways,
1267        > for F
1268    where
1269        T: Send + Sync + 'static,
1270        F: Fn() -> T + Send + Sync + 'static,
1271    {
1272        fn into_reactive_value(self) -> ArcSignal<Option<T>, SyncStorage> {
1273            ArcSignal::derive(move || Some(self()))
1274        }
1275    }
1276
1277    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1278    impl<T, F>
1279        crate::IntoReactiveValue<
1280            Signal<Option<T>, LocalStorage>,
1281            __IntoReactiveValueMarkerOptionalSignalFromReactiveClosureAlways,
1282        > for F
1283    where
1284        T: 'static,
1285        F: Fn() -> T + 'static,
1286    {
1287        fn into_reactive_value(self) -> Signal<Option<T>, LocalStorage> {
1288            Signal::derive_local(move || Some(self()))
1289        }
1290    }
1291
1292    #[cfg(not(all(feature = "nightly", rustc_nightly)))]
1293    impl<T, F>
1294        crate::IntoReactiveValue<
1295            ArcSignal<Option<T>, LocalStorage>,
1296            __IntoReactiveValueMarkerOptionalSignalFromReactiveClosureAlways,
1297        > for F
1298    where
1299        T: 'static,
1300        F: Fn() -> T + 'static,
1301    {
1302        fn into_reactive_value(self) -> ArcSignal<Option<T>, LocalStorage> {
1303            ArcSignal::derive_local(move || Some(self()))
1304        }
1305    }
1306
1307    #[allow(deprecated)]
1308    impl<T> From<MaybeSignal<T>> for Signal<T>
1309    where
1310        T: Send + Sync + 'static,
1311    {
1312        #[track_caller]
1313        fn from(value: MaybeSignal<T>) -> Self {
1314            match value {
1315                MaybeSignal::Static(value) => Signal::stored(value),
1316                MaybeSignal::Dynamic(signal) => signal,
1317            }
1318        }
1319    }
1320
1321    #[allow(deprecated)]
1322    impl<T> From<MaybeSignal<T, LocalStorage>> for Signal<T, LocalStorage>
1323    where
1324        T: Send + Sync + 'static,
1325    {
1326        #[track_caller]
1327        fn from(value: MaybeSignal<T, LocalStorage>) -> Self {
1328            match value {
1329                MaybeSignal::Static(value) => Signal::stored_local(value),
1330                MaybeSignal::Dynamic(signal) => signal,
1331            }
1332        }
1333    }
1334
1335    #[allow(deprecated)]
1336    impl<T> From<MaybeSignal<T>> for Signal<Option<T>>
1337    where
1338        T: Clone + Send + Sync + 'static,
1339    {
1340        #[track_caller]
1341        fn from(value: MaybeSignal<T>) -> Self {
1342            match value {
1343                MaybeSignal::Static(value) => Signal::stored(Some(value)),
1344                MaybeSignal::Dynamic(signal) => {
1345                    Signal::derive(move || Some(signal.get()))
1346                }
1347            }
1348        }
1349    }
1350
1351    #[allow(deprecated)]
1352    impl<T> From<MaybeSignal<T, LocalStorage>> for Signal<Option<T>, LocalStorage>
1353    where
1354        T: Clone + Send + Sync + 'static,
1355    {
1356        #[track_caller]
1357        fn from(value: MaybeSignal<T, LocalStorage>) -> Self {
1358            match value {
1359                MaybeSignal::Static(value) => Signal::stored_local(Some(value)),
1360                MaybeSignal::Dynamic(signal) => {
1361                    Signal::derive_local(move || Some(signal.get()))
1362                }
1363            }
1364        }
1365    }
1366
1367    impl<T> From<MaybeProp<T>> for Option<Signal<Option<T>>>
1368    where
1369        T: Send + Sync + 'static,
1370    {
1371        #[track_caller]
1372        fn from(value: MaybeProp<T>) -> Self {
1373            value.0
1374        }
1375    }
1376
1377    impl<T> From<MaybeProp<T, LocalStorage>>
1378        for Option<Signal<Option<T>, LocalStorage>>
1379    where
1380        T: Send + Sync + 'static,
1381    {
1382        #[track_caller]
1383        fn from(value: MaybeProp<T, LocalStorage>) -> Self {
1384            value.0
1385        }
1386    }
1387
1388    /// A wrapper for a value that is *either* `T` or [`Signal<T>`].
1389    ///
1390    /// This allows you to create APIs that take either a reactive or a non-reactive value
1391    /// of the same type. This is especially useful for component properties.
1392    ///
1393    /// ```
1394    /// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
1395    /// # use reactive_graph::wrappers::read::MaybeSignal;
1396    /// # use reactive_graph::computed::Memo;
1397    /// # use reactive_graph::prelude::*;
1398    /// let (count, set_count) = signal(2);
1399    /// let double_count = MaybeSignal::derive(move || count.get() * 2);
1400    /// let memoized_double_count = Memo::new(move |_| count.get() * 2);
1401    /// let static_value = 5;
1402    ///
1403    /// // this function takes either a reactive or non-reactive value
1404    /// fn above_3(arg: &MaybeSignal<i32>) -> bool {
1405    ///     // ✅ calling the signal clones and returns the value
1406    ///     //    it is a shorthand for arg.get()
1407    ///     arg.get() > 3
1408    /// }
1409    ///
1410    /// assert_eq!(above_3(&static_value.into()), true);
1411    /// assert_eq!(above_3(&count.into()), false);
1412    /// assert_eq!(above_3(&double_count), true);
1413    /// assert_eq!(above_3(&memoized_double_count.into()), true);
1414    /// ```
1415    #[derive(Debug, PartialEq, Eq)]
1416    #[deprecated(
1417        since = "0.7.0-rc3",
1418        note = "`MaybeSignal<T>` is deprecated in favour of `Signal<T>` which \
1419                is `Copy`, now has a more efficient From<T> implementation \
1420                and other benefits in 0.7."
1421    )]
1422    pub enum MaybeSignal<T, S = SyncStorage>
1423    where
1424        T: 'static,
1425        S: Storage<T>,
1426    {
1427        /// An unchanging value of type `T`.
1428        Static(T),
1429        /// A reactive signal that contains a value of type `T`.
1430        Dynamic(Signal<T, S>),
1431    }
1432
1433    #[allow(deprecated)]
1434    impl<T: Clone, S> Clone for MaybeSignal<T, S>
1435    where
1436        S: Storage<T>,
1437    {
1438        fn clone(&self) -> Self {
1439            match self {
1440                Self::Static(item) => Self::Static(item.clone()),
1441                Self::Dynamic(signal) => Self::Dynamic(*signal),
1442            }
1443        }
1444    }
1445
1446    #[allow(deprecated)]
1447    impl<T: Copy, S> Copy for MaybeSignal<T, S> where S: Storage<T> {}
1448
1449    #[allow(deprecated)]
1450    impl<T: Default, S> Default for MaybeSignal<T, S>
1451    where
1452        S: Storage<T>,
1453    {
1454        fn default() -> Self {
1455            Self::Static(Default::default())
1456        }
1457    }
1458
1459    #[allow(deprecated)]
1460    impl<T, S> DefinedAt for MaybeSignal<T, S>
1461    where
1462        S: Storage<T>,
1463    {
1464        fn defined_at(&self) -> Option<&'static Location<'static>> {
1465            // TODO this could be improved, but would require moving from an enum to a struct here.
1466            // Probably not worth it for relatively small benefits.
1467            None
1468        }
1469    }
1470
1471    #[allow(deprecated)]
1472    impl<T, S> Track for MaybeSignal<T, S>
1473    where
1474        S: Storage<T> + Storage<SignalTypes<T, S>>,
1475    {
1476        fn track(&self) {
1477            match self {
1478                Self::Static(_) => {}
1479                Self::Dynamic(signal) => signal.track(),
1480            }
1481        }
1482    }
1483
1484    #[allow(deprecated)]
1485    impl<T, S> ReadUntracked for MaybeSignal<T, S>
1486    where
1487        T: Clone,
1488        S: Storage<SignalTypes<T, S>> + Storage<T>,
1489    {
1490        type Value = ReadGuard<T, SignalReadGuard<T, S>>;
1491
1492        fn try_read_untracked(&self) -> Option<Self::Value> {
1493            match self {
1494                Self::Static(t) => {
1495                    Some(ReadGuard::new(SignalReadGuard::Owned(t.clone())))
1496                }
1497                Self::Dynamic(s) => s.try_read_untracked(),
1498            }
1499        }
1500
1501        fn custom_try_read(&self) -> Option<Option<Self::Value>> {
1502            match self {
1503                Self::Static(_) => None,
1504                Self::Dynamic(s) => s.custom_try_read(),
1505            }
1506        }
1507    }
1508
1509    #[allow(deprecated)]
1510    impl<T> MaybeSignal<T>
1511    where
1512        T: Send + Sync,
1513    {
1514        /// Wraps a derived signal, i.e., any computation that accesses one or more
1515        /// reactive signals.
1516        pub fn derive(
1517            derived_signal: impl Fn() -> T + Send + Sync + 'static,
1518        ) -> Self {
1519            Self::Dynamic(Signal::derive(derived_signal))
1520        }
1521    }
1522
1523    #[allow(deprecated)]
1524    impl<T> MaybeSignal<T, LocalStorage> {
1525        /// Wraps a derived signal, i.e., any computation that accesses one or more
1526        /// reactive signals.
1527        pub fn derive_local(derived_signal: impl Fn() -> T + 'static) -> Self {
1528            Self::Dynamic(Signal::derive_local(derived_signal))
1529        }
1530    }
1531
1532    #[allow(deprecated)]
1533    impl<T> From<T> for MaybeSignal<T, SyncStorage>
1534    where
1535        SyncStorage: Storage<T>,
1536    {
1537        fn from(value: T) -> Self {
1538            Self::Static(value)
1539        }
1540    }
1541
1542    #[allow(deprecated)]
1543    impl<T> FromLocal<T> for MaybeSignal<T, LocalStorage>
1544    where
1545        LocalStorage: Storage<T>,
1546    {
1547        fn from_local(value: T) -> Self {
1548            Self::Static(value)
1549        }
1550    }
1551
1552    #[allow(deprecated)]
1553    impl<T> From<ReadSignal<T>> for MaybeSignal<T>
1554    where
1555        T: Send + Sync,
1556    {
1557        fn from(value: ReadSignal<T>) -> Self {
1558            Self::Dynamic(value.into())
1559        }
1560    }
1561
1562    #[allow(deprecated)]
1563    impl<T> From<ReadSignal<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
1564        fn from(value: ReadSignal<T, LocalStorage>) -> Self {
1565            Self::Dynamic(value.into())
1566        }
1567    }
1568
1569    #[allow(deprecated)]
1570    impl<T> From<RwSignal<T>> for MaybeSignal<T>
1571    where
1572        T: Send + Sync,
1573    {
1574        fn from(value: RwSignal<T>) -> Self {
1575            Self::Dynamic(value.into())
1576        }
1577    }
1578
1579    #[allow(deprecated)]
1580    impl<T> From<RwSignal<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
1581        fn from(value: RwSignal<T, LocalStorage>) -> Self {
1582            Self::Dynamic(value.into())
1583        }
1584    }
1585
1586    #[allow(deprecated)]
1587    impl<T> From<Memo<T>> for MaybeSignal<T>
1588    where
1589        T: Send + Sync,
1590    {
1591        fn from(value: Memo<T>) -> Self {
1592            Self::Dynamic(value.into())
1593        }
1594    }
1595
1596    #[allow(deprecated)]
1597    impl<T> From<Memo<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
1598        fn from(value: Memo<T, LocalStorage>) -> Self {
1599            Self::Dynamic(value.into())
1600        }
1601    }
1602
1603    #[allow(deprecated)]
1604    impl<T> From<ArcReadSignal<T>> for MaybeSignal<T>
1605    where
1606        T: Send + Sync,
1607    {
1608        fn from(value: ArcReadSignal<T>) -> Self {
1609            ReadSignal::from(value).into()
1610        }
1611    }
1612
1613    #[allow(deprecated)]
1614    impl<T> FromLocal<ArcReadSignal<T>> for MaybeSignal<T, LocalStorage> {
1615        fn from_local(value: ArcReadSignal<T>) -> Self {
1616            ReadSignal::from_local(value).into()
1617        }
1618    }
1619
1620    #[allow(deprecated)]
1621    impl<T> From<ArcRwSignal<T>> for MaybeSignal<T>
1622    where
1623        T: Send + Sync + 'static,
1624    {
1625        fn from(value: ArcRwSignal<T>) -> Self {
1626            RwSignal::from(value).into()
1627        }
1628    }
1629
1630    #[allow(deprecated)]
1631    impl<T> FromLocal<ArcRwSignal<T>> for MaybeSignal<T, LocalStorage>
1632    where
1633        T: 'static,
1634    {
1635        fn from_local(value: ArcRwSignal<T>) -> Self {
1636            RwSignal::from_local(value).into()
1637        }
1638    }
1639
1640    #[allow(deprecated)]
1641    impl<T> From<ArcMemo<T>> for MaybeSignal<T>
1642    where
1643        T: Send + Sync,
1644    {
1645        fn from(value: ArcMemo<T>) -> Self {
1646            Memo::from(value).into()
1647        }
1648    }
1649
1650    #[allow(deprecated)]
1651    impl<T> FromLocal<ArcMemo<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
1652        fn from_local(value: ArcMemo<T, LocalStorage>) -> Self {
1653            Memo::from_local(value).into()
1654        }
1655    }
1656
1657    #[allow(deprecated)]
1658    impl<T, S> From<Signal<T, S>> for MaybeSignal<T, S>
1659    where
1660        S: Storage<T>,
1661    {
1662        fn from(value: Signal<T, S>) -> Self {
1663            Self::Dynamic(value)
1664        }
1665    }
1666
1667    #[allow(deprecated)]
1668    impl<S> From<&str> for MaybeSignal<String, S>
1669    where
1670        S: Storage<String> + Storage<Arc<RwLock<String>>>,
1671    {
1672        fn from(value: &str) -> Self {
1673            Self::Static(value.to_string())
1674        }
1675    }
1676
1677    /// A wrapping type for an optional component prop.
1678    ///
1679    /// This can either be a signal or a non-reactive value, and may or may not have a value.
1680    /// In other words, this is an `Option<Signal<Option<T>>>`, but automatically flattens its getters.
1681    ///
1682    /// This creates an extremely flexible type for component libraries, etc.
1683    ///
1684    /// ## Examples
1685    /// ```rust
1686    /// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
1687    /// # use reactive_graph::wrappers::read::MaybeProp;
1688    /// # use reactive_graph::computed::Memo;
1689    /// # use reactive_graph::prelude::*;
1690    /// let (count, set_count) = signal(Some(2));
1691    /// let double = |n| n * 2;
1692    /// let double_count = MaybeProp::derive(move || count.get().map(double));
1693    /// let memoized_double_count = Memo::new(move |_| count.get().map(double));
1694    /// let static_value = 5;
1695    ///
1696    /// // this function takes either a reactive or non-reactive value
1697    /// fn above_3(arg: &MaybeProp<i32>) -> bool {
1698    ///     // ✅ calling the signal clones and returns the value
1699    ///     //    it is a shorthand for arg.get()q
1700    ///     arg.get().map(|arg| arg > 3).unwrap_or(false)
1701    /// }
1702    ///
1703    /// assert_eq!(above_3(&None::<i32>.into()), false);
1704    /// assert_eq!(above_3(&static_value.into()), true);
1705    /// assert_eq!(above_3(&count.into()), false);
1706    /// assert_eq!(above_3(&double_count), true);
1707    /// assert_eq!(above_3(&memoized_double_count.into()), true);
1708    /// ```
1709    #[derive(Debug, PartialEq, Eq)]
1710    pub struct MaybeProp<T: 'static, S = SyncStorage>(
1711        pub(crate) Option<Signal<Option<T>, S>>,
1712    )
1713    where
1714        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>;
1715
1716    impl<T, S> Clone for MaybeProp<T, S>
1717    where
1718        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
1719    {
1720        fn clone(&self) -> Self {
1721            *self
1722        }
1723    }
1724
1725    impl<T, S> Copy for MaybeProp<T, S> where
1726        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>
1727    {
1728    }
1729
1730    impl<T, S> Default for MaybeProp<T, S>
1731    where
1732        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
1733    {
1734        fn default() -> Self {
1735            Self(None)
1736        }
1737    }
1738
1739    impl<T, S> DefinedAt for MaybeProp<T, S>
1740    where
1741        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
1742    {
1743        fn defined_at(&self) -> Option<&'static Location<'static>> {
1744            // TODO this can be improved by adding a defined_at field
1745            None
1746        }
1747    }
1748
1749    impl<T, S> Track for MaybeProp<T, S>
1750    where
1751        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
1752    {
1753        fn track(&self) {
1754            match &self.0 {
1755                None => {}
1756                Some(signal) => signal.track(),
1757            }
1758        }
1759    }
1760
1761    impl<T, S> ReadUntracked for MaybeProp<T, S>
1762    where
1763        S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
1764    {
1765        type Value = ReadGuard<Option<T>, SignalReadGuard<Option<T>, S>>;
1766
1767        fn try_read_untracked(&self) -> Option<Self::Value> {
1768            match &self.0 {
1769                None => Some(ReadGuard::new(SignalReadGuard::Owned(None))),
1770                Some(inner) => inner.try_read_untracked(),
1771            }
1772        }
1773
1774        fn custom_try_read(&self) -> Option<Option<Self::Value>> {
1775            match &self.0 {
1776                None => None,
1777                Some(inner) => inner.custom_try_read(),
1778            }
1779        }
1780    }
1781
1782    impl<T> MaybeProp<T>
1783    where
1784        T: Send + Sync,
1785    {
1786        /// Wraps a derived signal, i.e., any computation that accesses one or more
1787        /// reactive signals.
1788        pub fn derive(
1789            derived_signal: impl Fn() -> Option<T> + Send + Sync + 'static,
1790        ) -> Self {
1791            Self(Some(Signal::derive(derived_signal)))
1792        }
1793    }
1794
1795    impl<T> From<T> for MaybeProp<T>
1796    where
1797        T: Send + Sync,
1798        SyncStorage: Storage<Option<T>>,
1799    {
1800        fn from(value: T) -> Self {
1801            Self(Some(Signal::stored(Some(value))))
1802        }
1803    }
1804
1805    impl<T> From<Option<T>> for MaybeProp<T>
1806    where
1807        T: Send + Sync,
1808        SyncStorage: Storage<Option<T>>,
1809    {
1810        fn from(value: Option<T>) -> Self {
1811            Self(Some(Signal::stored(value)))
1812        }
1813    }
1814
1815    #[allow(deprecated)]
1816    impl<T> From<MaybeSignal<Option<T>>> for MaybeProp<T>
1817    where
1818        T: Send + Sync,
1819        SyncStorage: Storage<Option<T>>,
1820    {
1821        fn from(value: MaybeSignal<Option<T>>) -> Self {
1822            Self(Some(value.into()))
1823        }
1824    }
1825
1826    #[allow(deprecated)]
1827    impl<T> From<Option<MaybeSignal<Option<T>>>> for MaybeProp<T>
1828    where
1829        T: Send + Sync,
1830        SyncStorage: Storage<Option<T>>,
1831    {
1832        fn from(value: Option<MaybeSignal<Option<T>>>) -> Self {
1833            Self(value.map(Into::into))
1834        }
1835    }
1836
1837    impl<T> From<ReadSignal<Option<T>>> for MaybeProp<T>
1838    where
1839        T: Send + Sync,
1840    {
1841        fn from(value: ReadSignal<Option<T>>) -> Self {
1842            Self(Some(value.into()))
1843        }
1844    }
1845
1846    impl<T> From<RwSignal<Option<T>>> for MaybeProp<T>
1847    where
1848        T: Send + Sync,
1849    {
1850        fn from(value: RwSignal<Option<T>>) -> Self {
1851            Self(Some(value.into()))
1852        }
1853    }
1854
1855    impl<T> From<Memo<Option<T>>> for MaybeProp<T>
1856    where
1857        T: Send + Sync,
1858    {
1859        fn from(value: Memo<Option<T>>) -> Self {
1860            Self(Some(value.into()))
1861        }
1862    }
1863
1864    impl<T> From<Signal<Option<T>>> for MaybeProp<T>
1865    where
1866        T: Send + Sync,
1867        SyncStorage: Storage<Option<T>>,
1868    {
1869        fn from(value: Signal<Option<T>>) -> Self {
1870            Self(Some(value))
1871        }
1872    }
1873
1874    impl<T> From<ReadSignal<T>> for MaybeProp<T>
1875    where
1876        T: Send + Sync + Clone,
1877    {
1878        fn from(value: ReadSignal<T>) -> Self {
1879            Self(Some(Signal::derive(move || Some(value.get()))))
1880        }
1881    }
1882
1883    impl<T> From<RwSignal<T>> for MaybeProp<T>
1884    where
1885        T: Send + Sync + Clone,
1886    {
1887        fn from(value: RwSignal<T>) -> Self {
1888            Self(Some(Signal::derive(move || Some(value.get()))))
1889        }
1890    }
1891
1892    impl<T> From<Memo<T>> for MaybeProp<T>
1893    where
1894        T: Send + Sync + Clone,
1895    {
1896        fn from(value: Memo<T>) -> Self {
1897            Self(Some(Signal::derive(move || Some(value.get()))))
1898        }
1899    }
1900
1901    impl<T> From<Signal<T>> for MaybeProp<T>
1902    where
1903        T: Send + Sync + Clone,
1904    {
1905        fn from(value: Signal<T>) -> Self {
1906            Self(Some(Signal::derive(move || Some(value.get()))))
1907        }
1908    }
1909
1910    impl From<&str> for MaybeProp<String> {
1911        fn from(value: &str) -> Self {
1912            Self(Some(Signal::from(Some(value.to_string()))))
1913        }
1914    }
1915
1916    impl<T> MaybeProp<T, LocalStorage> {
1917        /// Wraps a derived signal, i.e., any computation that accesses one or more
1918        /// reactive signals.
1919        pub fn derive_local(
1920            derived_signal: impl Fn() -> Option<T> + 'static,
1921        ) -> Self {
1922            Self(Some(Signal::derive_local(derived_signal)))
1923        }
1924    }
1925
1926    impl<T> FromLocal<T> for MaybeProp<T, LocalStorage> {
1927        fn from_local(value: T) -> Self {
1928            Self(Some(Signal::stored_local(Some(value))))
1929        }
1930    }
1931
1932    impl<T> FromLocal<Option<T>> for MaybeProp<T, LocalStorage> {
1933        fn from_local(value: Option<T>) -> Self {
1934            Self(Some(Signal::stored_local(value)))
1935        }
1936    }
1937
1938    #[allow(deprecated)]
1939    impl<T> From<MaybeSignal<Option<T>, LocalStorage>>
1940        for MaybeProp<T, LocalStorage>
1941    where
1942        T: Send + Sync,
1943    {
1944        fn from(value: MaybeSignal<Option<T>, LocalStorage>) -> Self {
1945            Self(Some(value.into()))
1946        }
1947    }
1948
1949    #[allow(deprecated)]
1950    impl<T> From<Option<MaybeSignal<Option<T>, LocalStorage>>>
1951        for MaybeProp<T, LocalStorage>
1952    where
1953        T: Send + Sync,
1954    {
1955        fn from(value: Option<MaybeSignal<Option<T>, LocalStorage>>) -> Self {
1956            Self(value.map(Into::into))
1957        }
1958    }
1959
1960    impl<T> From<ReadSignal<Option<T>, LocalStorage>> for MaybeProp<T, LocalStorage>
1961    where
1962        T: Send + Sync,
1963    {
1964        fn from(value: ReadSignal<Option<T>, LocalStorage>) -> Self {
1965            Self(Some(value.into()))
1966        }
1967    }
1968
1969    impl<T> From<RwSignal<Option<T>, LocalStorage>> for MaybeProp<T, LocalStorage>
1970    where
1971        T: Send + Sync,
1972    {
1973        fn from(value: RwSignal<Option<T>, LocalStorage>) -> Self {
1974            Self(Some(value.into()))
1975        }
1976    }
1977
1978    impl<T> From<Memo<Option<T>, LocalStorage>> for MaybeProp<T, LocalStorage>
1979    where
1980        T: Send + Sync,
1981    {
1982        fn from(value: Memo<Option<T>, LocalStorage>) -> Self {
1983            Self(Some(value.into()))
1984        }
1985    }
1986
1987    impl<T> From<Signal<Option<T>, LocalStorage>> for MaybeProp<T, LocalStorage> {
1988        fn from(value: Signal<Option<T>, LocalStorage>) -> Self {
1989            Self(Some(value))
1990        }
1991    }
1992
1993    impl<T> From<ReadSignal<T, LocalStorage>> for MaybeProp<T, LocalStorage>
1994    where
1995        T: Send + Sync + Clone,
1996    {
1997        fn from(value: ReadSignal<T, LocalStorage>) -> Self {
1998            Self(Some(Signal::derive_local(move || Some(value.get()))))
1999        }
2000    }
2001
2002    impl<T> From<RwSignal<T, LocalStorage>> for MaybeProp<T, LocalStorage>
2003    where
2004        T: Send + Sync + Clone,
2005    {
2006        fn from(value: RwSignal<T, LocalStorage>) -> Self {
2007            Self(Some(Signal::derive_local(move || Some(value.get()))))
2008        }
2009    }
2010
2011    impl<T> From<Memo<T, LocalStorage>> for MaybeProp<T, LocalStorage>
2012    where
2013        T: Send + Sync + Clone,
2014    {
2015        fn from(value: Memo<T, LocalStorage>) -> Self {
2016            Self(Some(Signal::derive_local(move || Some(value.get()))))
2017        }
2018    }
2019
2020    impl<T> From<Signal<T, LocalStorage>> for MaybeProp<T, LocalStorage>
2021    where
2022        T: Send + Sync + Clone,
2023    {
2024        fn from(value: Signal<T, LocalStorage>) -> Self {
2025            Self(Some(Signal::derive_local(move || Some(value.get()))))
2026        }
2027    }
2028
2029    impl From<&str> for MaybeProp<String, LocalStorage> {
2030        fn from(value: &str) -> Self {
2031            Self(Some(Signal::stored_local(Some(value.to_string()))))
2032        }
2033    }
2034
2035    /// The content of a [`Signal`] wrapper read guard, variable depending on the signal type.
2036    pub enum SignalReadGuard<T: 'static, S: Storage<T>> {
2037        /// A read signal guard.
2038        Read(ReadGuard<T, Plain<T>>),
2039        #[allow(clippy::type_complexity)]
2040        /// A memo guard.
2041        Memo(
2042            ReadGuard<T, Mapped<Plain<Option<<S as Storage<T>>::Wrapped>>, T>>,
2043        ),
2044        /// A fake guard for derived signals, the content had to actually be cloned, so it's not a guard but we pretend it is.
2045        Owned(T),
2046    }
2047
2048    impl<T: 'static + std::fmt::Debug, S: Storage<T> + std::fmt::Debug>
2049        std::fmt::Debug for SignalReadGuard<T, S>
2050    where
2051        <S as Storage<T>>::Wrapped: std::fmt::Debug,
2052    {
2053        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2054            match self {
2055                Self::Read(arg0) => f.debug_tuple("Read").field(arg0).finish(),
2056                Self::Memo(arg0) => f.debug_tuple("Memo").field(arg0).finish(),
2057                Self::Owned(arg0) => {
2058                    f.debug_tuple("Owned").field(arg0).finish()
2059                }
2060            }
2061        }
2062    }
2063
2064    impl<T, S> Clone for SignalReadGuard<T, S>
2065    where
2066        S: Storage<T>,
2067        T: Clone,
2068        Plain<T>: Clone,
2069        Mapped<Plain<Option<<S as Storage<T>>::Wrapped>>, T>: Clone,
2070    {
2071        fn clone(&self) -> Self {
2072            match self {
2073                SignalReadGuard::Read(i) => SignalReadGuard::Read(i.clone()),
2074                SignalReadGuard::Memo(i) => SignalReadGuard::Memo(i.clone()),
2075                SignalReadGuard::Owned(i) => SignalReadGuard::Owned(i.clone()),
2076            }
2077        }
2078    }
2079
2080    impl<T, S> Deref for SignalReadGuard<T, S>
2081    where
2082        S: Storage<T>,
2083    {
2084        type Target = T;
2085        fn deref(&self) -> &Self::Target {
2086            match self {
2087                SignalReadGuard::Read(i) => i,
2088                SignalReadGuard::Memo(i) => i,
2089                SignalReadGuard::Owned(i) => i,
2090            }
2091        }
2092    }
2093
2094    impl<T, S> Borrow<T> for SignalReadGuard<T, S>
2095    where
2096        S: Storage<T>,
2097    {
2098        fn borrow(&self) -> &T {
2099            self.deref()
2100        }
2101    }
2102
2103    impl<T, S> PartialEq<T> for SignalReadGuard<T, S>
2104    where
2105        S: Storage<T>,
2106        T: PartialEq,
2107    {
2108        fn eq(&self, other: &T) -> bool {
2109            self.deref() == other
2110        }
2111    }
2112
2113    impl<T, S> Display for SignalReadGuard<T, S>
2114    where
2115        S: Storage<T>,
2116        T: Display,
2117    {
2118        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2119            Display::fmt(&**self, f)
2120        }
2121    }
2122}
2123
2124/// Types that abstract over the ability to update a signal.
2125pub mod write {
2126    use crate::{
2127        owner::{ArenaItem, Storage, SyncStorage},
2128        signal::{ArcRwSignal, ArcWriteSignal, RwSignal, WriteSignal},
2129        traits::Set,
2130    };
2131
2132    /// Helper trait for converting `Fn(T)` into [`SignalSetter<T>`].
2133    pub trait IntoSignalSetter<T, S>: Sized {
2134        /// Consumes `self`, returning [`SignalSetter<T>`].
2135        fn into_signal_setter(self) -> SignalSetter<T, S>;
2136    }
2137
2138    impl<F, T, S> IntoSignalSetter<T, S> for F
2139    where
2140        F: Fn(T) + 'static + Send + Sync,
2141        S: Storage<Box<dyn Fn(T) + Send + Sync>>,
2142    {
2143        fn into_signal_setter(self) -> SignalSetter<T, S> {
2144            SignalSetter::map(self)
2145        }
2146    }
2147
2148    /// A wrapper for any kind of settable reactive signal: a [`WriteSignal`],
2149    /// [`RwSignal`], or closure that receives a value and sets a signal depending
2150    /// on it.
2151    ///
2152    /// This allows you to create APIs that take any kind of `SignalSetter<T>` as an argument,
2153    /// rather than adding a generic `F: Fn(T)`. Values can be set with the same
2154    /// function call or `set()`, API as other signals.
2155    ///
2156    /// ## Core Trait Implementations
2157    /// - [`.set()`](#impl-SignalSet<T>-for-SignalSetter<T>) (or calling the setter as a function)
2158    ///   sets the signal’s value, and notifies all subscribers that the signal’s value has changed.
2159    ///   to subscribe to the signal, and to re-run whenever the value of the signal changes.
2160    ///
2161    /// ## Examples
2162    /// ```rust
2163    /// # use reactive_graph::prelude::*;  let owner = reactive_graph::owner::Owner::new(); owner.set();
2164    /// # use reactive_graph::wrappers::write::SignalSetter;
2165    /// # use reactive_graph::signal::signal;
2166    /// let (count, set_count) = signal(2);
2167    /// let set_double_input = SignalSetter::map(move |n| set_count.set(n * 2));
2168    ///
2169    /// // this function takes any kind of signal setter
2170    /// fn set_to_4(setter: &SignalSetter<i32>) {
2171    ///     // ✅ calling the signal sets the value
2172    ///     //    can be `setter(4)` on nightly
2173    ///     setter.set(4);
2174    /// }
2175    ///
2176    /// set_to_4(&set_count.into());
2177    /// assert_eq!(count.get(), 4);
2178    /// set_to_4(&set_double_input);
2179    /// assert_eq!(count.get(), 8);
2180    /// ```
2181    #[derive(Debug, PartialEq, Eq)]
2182    pub struct SignalSetter<T, S = SyncStorage>
2183    where
2184        T: 'static,
2185    {
2186        inner: SignalSetterTypes<T, S>,
2187        #[cfg(any(debug_assertions, leptos_debuginfo))]
2188        defined_at: &'static std::panic::Location<'static>,
2189    }
2190
2191    impl<T, S> Clone for SignalSetter<T, S> {
2192        fn clone(&self) -> Self {
2193            *self
2194        }
2195    }
2196
2197    impl<T: Default + 'static, S> Default for SignalSetter<T, S> {
2198        #[track_caller]
2199        fn default() -> Self {
2200            Self {
2201                inner: SignalSetterTypes::Default,
2202                #[cfg(any(debug_assertions, leptos_debuginfo))]
2203                defined_at: std::panic::Location::caller(),
2204            }
2205        }
2206    }
2207
2208    impl<T, S> Copy for SignalSetter<T, S> {}
2209
2210    impl<T, S> Set for SignalSetter<T, S>
2211    where
2212        T: 'static,
2213        S: Storage<ArcWriteSignal<T>> + Storage<Box<dyn Fn(T) + Send + Sync>>,
2214    {
2215        type Value = T;
2216
2217        fn set(&self, new_value: Self::Value) {
2218            match self.inner {
2219                SignalSetterTypes::Default => {}
2220                SignalSetterTypes::Write(w) => w.set(new_value),
2221                SignalSetterTypes::Mapped(s) => {
2222                    s.try_with_value(|setter| setter(new_value));
2223                }
2224            }
2225        }
2226
2227        fn try_set(&self, new_value: Self::Value) -> Option<Self::Value> {
2228            match self.inner {
2229                SignalSetterTypes::Default => Some(new_value),
2230                SignalSetterTypes::Write(w) => w.try_set(new_value),
2231                SignalSetterTypes::Mapped(s) => {
2232                    let mut new_value = Some(new_value);
2233
2234                    let _ = s.try_with_value(|setter| {
2235                        setter(new_value.take().unwrap())
2236                    });
2237
2238                    new_value
2239                }
2240            }
2241        }
2242    }
2243
2244    impl<T, S> SignalSetter<T, S>
2245    where
2246        S: Storage<Box<dyn Fn(T) + Send + Sync>>,
2247    {
2248        /// Wraps a signal-setting closure, i.e., any computation that sets one or more reactive signals.
2249        #[track_caller]
2250        pub fn map(mapped_setter: impl Fn(T) + Send + Sync + 'static) -> Self {
2251            Self {
2252                inner: SignalSetterTypes::Mapped(ArenaItem::new_with_storage(
2253                    Box::new(mapped_setter),
2254                )),
2255                #[cfg(any(debug_assertions, leptos_debuginfo))]
2256                defined_at: std::panic::Location::caller(),
2257            }
2258        }
2259    }
2260
2261    impl<T, S> From<WriteSignal<T, S>> for SignalSetter<T, S> {
2262        #[track_caller]
2263        fn from(value: WriteSignal<T, S>) -> Self {
2264            Self {
2265                inner: SignalSetterTypes::Write(value),
2266                #[cfg(any(debug_assertions, leptos_debuginfo))]
2267                defined_at: std::panic::Location::caller(),
2268            }
2269        }
2270    }
2271
2272    impl<T, S> From<RwSignal<T, S>> for SignalSetter<T, S>
2273    where
2274        T: Send + Sync + 'static,
2275        S: Storage<ArcRwSignal<T>> + Storage<ArcWriteSignal<T>>,
2276    {
2277        #[track_caller]
2278        fn from(value: RwSignal<T, S>) -> Self {
2279            Self {
2280                inner: SignalSetterTypes::Write(value.write_only()),
2281                #[cfg(any(debug_assertions, leptos_debuginfo))]
2282                defined_at: std::panic::Location::caller(),
2283            }
2284        }
2285    }
2286
2287    enum SignalSetterTypes<T, S = SyncStorage>
2288    where
2289        T: 'static,
2290    {
2291        Write(WriteSignal<T, S>),
2292        Mapped(ArenaItem<Box<dyn Fn(T) + Send + Sync>, S>),
2293        Default,
2294    }
2295
2296    impl<T, S> Clone for SignalSetterTypes<T, S> {
2297        fn clone(&self) -> Self {
2298            *self
2299        }
2300    }
2301
2302    impl<T, S> Copy for SignalSetterTypes<T, S> {}
2303
2304    impl<T, S> core::fmt::Debug for SignalSetterTypes<T, S>
2305    where
2306        T: core::fmt::Debug,
2307        S: core::fmt::Debug,
2308    {
2309        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2310            match self {
2311                Self::Write(arg0) => {
2312                    f.debug_tuple("WriteSignal").field(arg0).finish()
2313                }
2314                Self::Mapped(_) => f.debug_tuple("Mapped").finish(),
2315                Self::Default => {
2316                    f.debug_tuple("SignalSetter<Default>").finish()
2317                }
2318            }
2319        }
2320    }
2321
2322    impl<T, S> PartialEq for SignalSetterTypes<T, S>
2323    where
2324        T: PartialEq,
2325    {
2326        fn eq(&self, other: &Self) -> bool {
2327            match (self, other) {
2328                (Self::Write(l0), Self::Write(r0)) => l0 == r0,
2329                (Self::Mapped(l0), Self::Mapped(r0)) => std::ptr::eq(l0, r0),
2330                _ => false,
2331            }
2332        }
2333    }
2334
2335    impl<T, S> Eq for SignalSetterTypes<T, S> where T: PartialEq {}
2336}