use super::{Freeze, MakeRx, MakeUnrx};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::ops::Deref;
#[cfg(any(client, doc))]
use sycamore::prelude::Scope;
use sycamore::prelude::{create_rc_signal, RcSignal};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct RxResult<T, E>(Result<T, E>)
where
T: MakeRx + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Clone + 'static;
impl<T, E> MakeRx for RxResult<T, E>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Serialize + DeserializeOwned + Clone + 'static,
{
type Rx = RxResultRx<T, E>;
fn make_rx(self) -> Self::Rx {
match self.0 {
Ok(state) => RxResultRx(create_rc_signal(Ok(state.make_rx()))),
Err(err) => RxResultRx(create_rc_signal(Err(err))),
}
}
}
#[derive(Clone, Debug)]
pub struct RxResultRx<T, E>(RcSignal<Result<T::Rx, E>>)
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Serialize + DeserializeOwned + Clone + 'static;
impl<T, E> MakeUnrx for RxResultRx<T, E>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Serialize + DeserializeOwned + Clone + 'static,
{
type Unrx = RxResult<T, E>;
fn make_unrx(self) -> Self::Unrx {
match &*self.0.get_untracked() {
Ok(state) => RxResult(Ok(state.clone().make_unrx())),
Err(err) => RxResult(Err(err.clone())),
}
}
#[cfg(any(client, doc))]
fn compute_suspense(&self, _cx: Scope<'_>) {}
}
impl<T, E> Freeze for RxResultRx<T, E>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Serialize + DeserializeOwned + Clone + 'static,
{
fn freeze(&self) -> String {
let self_clone = Self(self.0.clone());
let unrx = self_clone.make_unrx();
serde_json::to_string(&unrx).unwrap()
}
}
impl<T, E> Deref for RxResultRx<T, E>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Serialize + DeserializeOwned + Clone + 'static,
{
type Target = RcSignal<Result<T::Rx, E>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, E> From<Result<T, E>> for RxResult<T, E>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
<T as MakeRx>::Rx: MakeUnrx<Unrx = T> + Freeze + Clone + 'static,
E: Serialize + DeserializeOwned + Clone + 'static,
{
fn from(val: Result<T, E>) -> Self {
Self(val)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SerdeInfallible;