use leptos::*; use std::pin::Pin; pub enum MaybeRwSignal where T: 'static, { Static(T), DynamicRw(ReadSignal, WriteSignal), DynamicRead(Signal), } impl Clone for MaybeRwSignal { fn clone(&self) -> Self { match self { Self::Static(t) => Self::Static(t.clone()), Self::DynamicRw(r, w) => Self::DynamicRw(r, w), Self::DynamicRead(s) => Self::DynamicRead(s), } } } impl Copy for MaybeRwSignal {} impl From for MaybeRwSignal { fn from(t: T) -> Self { Self::Static(t) } } impl Default for MaybeRwSignal { fn default() -> Self { Self::Static(T::default()) } } impl From> for MaybeRwSignal { fn from(s: Signal) -> Self { Self::DynamicRead(s) } } impl From> for MaybeRwSignal { fn from(s: ReadSignal) -> Self { Self::DynamicRead(s.into()) } } impl From> for MaybeRwSignal { fn from(s: Memo) -> Self { Self::DynamicRead(s.into()) } } impl From> for MaybeRwSignal { fn from(s: RwSignal) -> Self { let (r, w) = s.split(); Self::DynamicRw(r, w) } } impl From<(ReadSignal, WriteSignal)> for MaybeRwSignal { fn from(s: (ReadSignal, WriteSignal)) -> Self { Self::DynamicRw(s.0, s.1) } } impl From<&str> for MaybeRwSignal { fn from(s: &str) -> Self { Self::Static(s.to_string()) } } impl SignalGet for MaybeRwSignal { fn get(&self) -> T { match self { Self::Static(t) => t.clone(), Self::DynamicRw(r, _) => r.get(), Self::DynamicRead(s) => s.get(), } } fn try_get(&self) -> Option { match self { Self::Static(t) => Some(t.clone()), Self::DynamicRw(r, _) => r.try_get(), Self::DynamicRead(s) => s.try_get(), } } } impl SignalWith for MaybeRwSignal { fn with(&self, f: impl FnOnce(&T) -> O) -> O { match self { Self::Static(t) => f(t), Self::DynamicRw(r, w) => r.with(f), Self::DynamicRead(s) => s.with(f), } } fn try_with(&self, f: impl FnOnce(&T) -> O) -> Option { match self { Self::Static(t) => Some(f(t)), Self::DynamicRw(r, _) => r.try_with(f), Self::DynamicRead(s) => s.try_with(f), } } } impl SignalWithUntracked for MaybeRwSignal { fn with_untracked(&self, f: impl FnOnce(&T) -> O) -> O { match self { Self::Static(t) => f(t), Self::DynamicRw(r, _) => r.with_untracked(f), Self::DynamicRead(s) => s.with_untracked(f), } } fn try_with_untracked(&self, f: impl FnOnce(&T) -> O) -> Option { match self { Self::Static(t) => Some(f(t)), Self::DynamicRw(r, _) => r.try_with_untracked(f), Self::DynamicRead(s) => s.try_with_untracked(f), } } } impl SignalGetUntracked for MaybeRwSignal { fn get_untracked(&self) -> T { match self { Self::Static(t) => t.clone(), Self::DynamicRw(r, _) => r.get_untracked(), Self::DynamicRead(s) => s.get_untracked(), } } fn try_get_untracked(&self) -> Option { match self { Self::Static(t) => Some(t.clone()), Self::DynamicRw(r, _) => r.try_get_untracked(), Self::DynamicRead(s) => s.try_get_untracked(), } } } impl SignalStream for MaybeRwSignal { fn to_stream(&self, cx: Scope) -> Pin>> { match self { Self::Static(t) => { let t = t.clone(); let stream = futures::stream::once(async move { t }); Box::bin(stream) } Self::DynamicRw(r, _) => r.to_stream(cx), Self::DynamicRead(s) => s.to_stream(cx), } } } impl MaybeRwSignal { pub fn derive(cx: Scope, derived_signal: impl Fn() -> T + 'static) -> Self { Self::DynamicRead(Signal::derive(cx, derived_signal)) } } impl SignalSetUntracked for MaybeRwSignal { fn set_untracked(&self, new_value: T) { match self { Self::DynamicRw(_, w) => w.set_untracked(new_value), _ => { // do nothing } } } fn try_set_untracked(&self, new_value: T) -> Option { match self { Self::DynamicRw(_, w) => w.try_set_untracked(new_value), _ => Some(new_value), } } } impl SignalUpdateUntracked for MaybeRwSignal { #[inline(always)] fn update_untracked(&self, f: impl FnOnce(&mut T)) { match self { Self::DynamicRw(_, w) => w.update_untracked(f), _ => { // do nothing } } } #[inline(always)] fn try_update_untracked(&self, f: impl FnOnce(&mut T) -> O) -> Option { match self { Self::DynamicRw(_, w) => w.try_update_untracked(f), _ => Some(f()), } } } impl SignalUpdate for MaybeRwSignal { #[inline(always)] fn update(&self, f: impl FnOnce(&mut T)) { match self { Self::DynamicRw(_, w) => w.update(f), _ => { // do nothing } } } #[inline(always)] fn try_update(&self, f: impl FnOnce(&mut T) -> O) -> Option { match self { Self::DynamicRw(_, w) => w.try_update(f), _ => Some(f()), } } } impl SignalSet for MaybeRwSignal { #[inline(always)] fn set(&self, new_value: T) { match self { Self::DynamicRw(_, w) => w.set(new_value), _ => { // do nothing } } } fn try_set(&self, new_value: T) -> Option { match self { Self::DynamicRw(_, w) => w.try_set(new_value), _ => Some(new_value), } } } impl SignalDispose for MaybeRwSignal { fn dispose(self) { match self { Self::DynamicRw(r, w) => { r.dispose(); w.dispose(); } Self::DynamicRead(s) => s.dispose(), _ => { // do nothing } } } }