use alloc::boxed::Box;
use alloc::sync::Arc;
use core::fmt::Display;
use futures_intrusive::channel::shared::{StateReceiver, StateSender};
use futures_intrusive::channel::StateId;
pub use state_atomic::StateAtomic;
pub use state_generic::StateGeneric;
pub use state_mutex::StateMutex;
pub use state_vec::StateVec;
use crate::channel::Channel;
use crate::component::Component;
mod state_atomic;
mod state_generic;
mod state_mutex;
mod state_vec;
pub trait StateTrait: Clone + Component + Eq {
type Value: Clone + Display;
type Store;
type Channel: Clone;
fn value(&self) -> Self::Value;
fn tx(&self) -> StateSender<Self::Channel>;
fn rx(&self) -> StateReceiver<Self::Channel>;
fn put(&self, value: Self::Value);
fn pointer(&self) -> Arc<Self::Store>;
fn update(&self);
}
pub(crate) fn from<T, U, F>(new: T, state: &U, mut func: F) -> T
where
T: StateTrait + 'static,
U: StateTrait + 'static,
F: FnMut(U::Value) -> T::Value + 'static,
{
let new_move = new.clone();
let state_value = state.clone();
let rx = state.rx();
wasm_bindgen_futures::spawn_local(async move {
let mut old = StateId::new();
while let Some((new, _)) = rx.receive(old).await {
new_move.put(func(state_value.value()));
new_move.update();
old = new;
}
});
new
}
pub(crate) async fn change(node: impl AsRef<web_sys::Node>, rx: StateReceiver<Channel>) {
let mut old = StateId::new();
while let Some((new, value)) = rx.receive(old).await {
node.as_ref().set_node_value(Some(&value));
old = new;
}
}
pub(crate) async fn state_change(mut func: Box<dyn FnMut(&str)>, rx: StateReceiver<Channel>) {
let mut old = StateId::new();
while let Some((new, value)) = rx.receive(old).await {
func(value.as_str());
old = new;
}
}