use crate::state::{Freeze, MakeRx, MakeUnrx};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::ops::Deref;
#[cfg(any(client, doc))]
use sycamore::prelude::Scope;
use sycamore::reactive::{create_rc_signal, RcSignal};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct RxVecNested<T>(Vec<T>)
where
T: MakeRx + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RxVecNestedRx<T>(RcSignal<Vec<T::Rx>>)
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone;
impl<T> MakeRx for RxVecNested<T>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone,
{
type Rx = RxVecNestedRx<T>;
fn make_rx(self) -> Self::Rx {
RxVecNestedRx(create_rc_signal(
self.0.into_iter().map(|x| x.make_rx()).collect(),
))
}
}
impl<T> MakeUnrx for RxVecNestedRx<T>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone,
{
type Unrx = RxVecNested<T>;
fn make_unrx(self) -> Self::Unrx {
let vec = (*self.0.get_untracked()).clone();
RxVecNested(vec.into_iter().map(|x| x.make_unrx()).collect())
}
#[cfg(any(client, doc))]
fn compute_suspense(&self, cx: Scope) {
for elem in self.0.get_untracked().iter() {
elem.compute_suspense(cx);
}
}
}
impl<T> Deref for RxVecNested<T>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone,
{
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> Deref for RxVecNestedRx<T>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone,
{
type Target = RcSignal<Vec<T::Rx>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> From<Vec<T>> for RxVecNested<T>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone,
{
fn from(value: Vec<T>) -> Self {
Self(value)
}
}
impl<T> Freeze for RxVecNestedRx<T>
where
T: MakeRx + Serialize + DeserializeOwned + 'static,
T::Rx: MakeUnrx<Unrx = T> + Freeze + Clone,
{
fn freeze(&self) -> String {
let unrx = Self(self.0.clone()).make_unrx();
serde_json::to_string(&unrx).unwrap()
}
}