use std::rc::Rc;
use crate::{RwSignal, Scope, WriteSignal};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SignalSetter<T>(SignalSetterTypes<T>)
where
T: 'static;
impl<T> SignalSetter<T>
where
T: 'static,
{
pub fn map(cx: Scope, mapped_setter: impl Fn(T) + 'static) -> Self {
Self(SignalSetterTypes::Mapped(cx, Rc::new(mapped_setter)))
}
pub fn set(&self, value: T) {
match &self.0 {
SignalSetterTypes::Write(s) => s.set(value),
SignalSetterTypes::Mapped(_, s) => s(value),
}
}
}
impl<T> From<WriteSignal<T>> for SignalSetter<T> {
fn from(value: WriteSignal<T>) -> Self {
Self(SignalSetterTypes::Write(value))
}
}
impl<T> From<RwSignal<T>> for SignalSetter<T> {
fn from(value: RwSignal<T>) -> Self {
Self(SignalSetterTypes::Write(value.write_only()))
}
}
#[derive(Clone)]
enum SignalSetterTypes<T>
where
T: 'static,
{
Write(WriteSignal<T>),
Mapped(Scope, Rc<dyn Fn(T)>),
}
impl<T> std::fmt::Debug for SignalSetterTypes<T>
where
T: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Write(arg0) => f.debug_tuple("WriteSignal").field(arg0).finish(),
Self::Mapped(_, _) => f.debug_tuple("Mapped").finish(),
}
}
}
impl<T> PartialEq for SignalSetterTypes<T>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Write(l0), Self::Write(r0)) => l0 == r0,
(Self::Mapped(_, l0), Self::Mapped(_, r0)) => std::ptr::eq(l0, r0),
_ => false,
}
}
}
impl<T> Eq for SignalSetterTypes<T> where T: PartialEq {}
#[cfg(not(feature = "stable"))]
impl<T> FnOnce<(T,)> for SignalSetter<T>
where
T: 'static,
{
type Output = ();
extern "rust-call" fn call_once(self, args: (T,)) -> Self::Output {
self.set(args.0)
}
}
#[cfg(not(feature = "stable"))]
impl<T> FnMut<(T,)> for SignalSetter<T>
where
T: 'static,
{
extern "rust-call" fn call_mut(&mut self, args: (T,)) -> Self::Output {
self.set(args.0)
}
}
#[cfg(not(feature = "stable"))]
impl<T> Fn<(T,)> for SignalSetter<T>
where
T: 'static,
{
extern "rust-call" fn call(&self, args: (T,)) -> Self::Output {
self.set(args.0)
}
}