pub type BoxSignalFn<T> = Box<dyn Fn() -> Pin<Box<dyn Signal<Item = T>>>>;
pub fn box_signal_fn<T, S: Signal<Item = T> + 'static>(f: impl Fn() -> S + 'static) -> BoxSignalFn<T> {
Box::new(move || {
Box::pin(f())
})
}
pub type RcSignalFn<T> = Rc<dyn Fn() -> Pin<Box<dyn Signal<Item = T>>>>;
pub fn rc_signal_fn<T, S: Signal<Item = T> + 'static>(f: impl Fn() -> S + 'static) -> RcSignalFn<T> {
Rc::new(move || {
Box::pin(f())
})
}
use futures_signals::signal::{Signal, SignalExt};
use std::marker::Unpin;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::rc::Rc;
pub struct DefaultSignal<S, T>
where
S: Signal<Item = T>,
{
default: Option<T>,
value_signal: Option<S>,
const_has_fired: bool,
}
impl<S, T> DefaultSignal<S, T>
where
S: Signal<Item = T>,
{
pub fn new(default: T, value_signal: Option<S>) -> Self {
Self {
default: Some(default),
value_signal,
const_has_fired: false,
}
}
}
impl<S, T> Signal for DefaultSignal<S, T>
where
S: Signal<Item = T> + Unpin,
T: Unpin,
{
type Item = T;
fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let _self = self.get_mut();
match &mut _self.value_signal {
None => {
if _self.const_has_fired {
Poll::Ready(None)
} else {
_self.const_has_fired = true;
Poll::Ready(_self.default.take())
}
}
Some(value_signal) => value_signal.poll_change_unpin(cx),
}
}
}
pub struct OptionSignal<S, T>
where
S: Signal<Item = T>,
{
value_signal: Option<S>,
const_has_fired: bool,
}
impl<S, T> OptionSignal<S, T>
where
S: Signal<Item = T>,
{
pub fn new(value_signal: Option<S>) -> Self {
Self {
value_signal,
const_has_fired: false,
}
}
}
impl<S, T> Signal for OptionSignal<S, T>
where
S: Signal<Item = T> + Unpin,
T: Unpin,
{
type Item = Option<T>;
fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
let _self = self.get_mut();
match &mut _self.value_signal {
None => {
if _self.const_has_fired {
Poll::Ready(None)
} else {
_self.const_has_fired = true;
Poll::Ready(Some(None))
}
}
Some(value_signal) => {
value_signal
.poll_change_unpin(cx)
.map(|value| value.map(|value| Some(value)))
}
}
}
}
pub enum EitherSignal<Left, Right> {
Left(Left),
Right(Right),
}
impl<Left, Right, T> Signal for EitherSignal<Left, Right>
where
Left: Signal<Item = T> + Unpin,
Right: Signal<Item = T> + Unpin,
{
type Item = T;
fn poll_change(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
match self.get_mut() {
Self::Left(x) => x.poll_change_unpin(cx),
Self::Right(x) => x.poll_change_unpin(cx),
}
}
}