Trait pinwheel::prelude::SignalExt[][src]

pub trait SignalExt: Signal {
Show methods fn to_stream(self) -> SignalStream<Self> { ... }
fn to_future(self) -> SignalFuture<Self>

Notable traits for SignalFuture<A>

impl<A> Future for SignalFuture<A> where
    A: Signal
type Output = <A as Signal>::Item;
{ ... }
fn map<A, B>(self, callback: B) -> Map<Self, B>
    where
        B: FnMut(Self::Item) -> A
, { ... }
fn inspect<A>(self, callback: A) -> Inspect<Self, A>
    where
        A: FnMut(&Self::Item)
, { ... }
fn eq(self, value: Self::Item) -> Eq<Self>
    where
        Self::Item: PartialEq<Self::Item>
, { ... }
fn neq(self, value: Self::Item) -> Neq<Self>
    where
        Self::Item: PartialEq<Self::Item>
, { ... }
fn dedupe_map<A, B>(self, callback: B) -> DedupeMap<Self, B>
    where
        B: FnMut(&mut Self::Item) -> A,
        Self::Item: PartialEq<Self::Item>
, { ... }
fn dedupe(self) -> Dedupe<Self>
    where
        Self::Item: PartialEq<Self::Item>
, { ... }
fn dedupe_cloned(self) -> DedupeCloned<Self>
    where
        Self::Item: PartialEq<Self::Item>
, { ... }
fn map_future<A, B>(self, callback: B) -> MapFuture<Self, A, B>
    where
        B: FnMut(Self::Item) -> A,
        A: Future
, { ... }
fn filter_map<A, B>(self, callback: B) -> FilterMap<Self, B>
    where
        B: FnMut(Self::Item) -> Option<A>
, { ... }
fn throttle<A, B>(self, callback: B) -> Throttle<Self, A, B>
    where
        B: FnMut() -> A,
        A: Future<Output = ()>
, { ... }
fn flatten(self) -> Flatten<Self>
    where
        Self::Item: Signal
, { ... }
fn switch<A, B>(self, callback: B) -> Switch<Self, A, B>
    where
        B: FnMut(Self::Item) -> A,
        A: Signal
, { ... }
fn switch_signal_vec<A, F>(self, callback: F) -> SwitchSignalVec<Self, A, F>
    where
        F: FnMut(Self::Item) -> A,
        A: SignalVec
, { ... }
fn for_each<U, F>(self, callback: F) -> ForEach<Self, U, F>

Notable traits for ForEach<A, B, C>

impl<A, B, C> Future for ForEach<A, B, C> where
    C: FnMut(<A as Signal>::Item) -> B,
    B: Future<Output = ()>,
    A: Signal
type Output = ();

    where
        F: FnMut(Self::Item) -> U,
        U: Future<Output = ()>
, { ... }
fn to_signal_vec(self) -> SignalSignalVec<Self> { ... }
fn wait_for(self, value: Self::Item) -> WaitFor<Self>

Notable traits for WaitFor<A>

impl<A> Future for WaitFor<A> where
    A: Signal,
    <A as Signal>::Item: PartialEq<<A as Signal>::Item>, 
type Output = Option<<A as Signal>::Item>;

    where
        Self::Item: PartialEq<Self::Item>
, { ... }
fn first(self) -> First<Self> { ... }
fn poll_change_unpin(
        &mut self,
        cx: &mut Context<'_>
    ) -> Poll<Option<Self::Item>>
    where
        Self: Unpin
, { ... }
fn boxed<'a>(
        self
    ) -> Pin<Box<dyn Signal<Item = Self::Item> + Send + 'a, Global>>
    where
        Self: Send + 'a
, { ... }
fn boxed_local<'a>(
        self
    ) -> Pin<Box<dyn Signal<Item = Self::Item> + 'a, Global>>
    where
        Self: 'a
, { ... }
}

Provided methods

Creates a Stream which contains the values of self.

When the output Stream is spawned:

  1. It immediately outputs the current value of self.

  2. Whenever self changes it outputs the new value of self.

Like all of the Signal methods, to_stream might skip intermediate changes. So you cannot rely upon it containing every intermediate change. But you can rely upon it always containing the most recent change.

Performance

This is extremely efficient: it is guaranteed constant time, and it does not do any heap allocation.

Creates a Signal which uses a closure to transform the value.

When the output Signal is spawned:

  1. It calls the closure with the current value of self.

  2. Then it puts the return value of the closure into the output Signal.

  3. Whenever self changes it repeats the above steps.

    This happens automatically and efficiently.

It will call the closure at most once for each change in self.

Like all of the Signal methods, map might skip intermediate changes. So you cannot rely upon the closure being called for every intermediate change. But you can rely upon it always being called with the most recent change.

Examples

Add 1 to the value:

let mapped = input.map(|value| value + 1);

mapped will always contain the current value of input, except with 1 added to it.

If input has the value 10, then mapped will have the value 11.

If input has the value 5, then mapped will have the value 6, etc.


Formatting to a String:

let mapped = input.map(|value| format!("{}", value));

mapped will always contain the current value of input, except formatted as a String.

If input has the value 10, then mapped will have the value "10".

If input has the value 5, then mapped will have the value "5", etc.

Performance

This is extremely efficient: it is guaranteed constant time, and it does not do any heap allocation.

Creates a Signal which uses a closure to transform the value.

This is exactly the same as map, except:

  1. It calls the closure with a mutable reference to the input value.

  2. If the new input value is the same as the old input value, it will not call the closure, instead it will completely ignore the new value, like as if it never happened.

    It uses the PartialEq implementation to determine whether the new value is the same as the old value.

    It only keeps track of the most recent value: that means that it won’t call the closure for consecutive duplicates, however it will call the closure for non-consecutive duplicates.

Because dedupe_map has the same behavior as map, it is useful solely as a performance optimization.

Performance

The performance is the same as map, except with an additional call to eq.

If the eq call is fast, then dedupe_map can be faster than map, because it doesn’t call the closure when the new and old values are the same, and it also doesn’t update any child Signals.

On the other hand, if the eq call is slow, then dedupe_map is probably slower than map.

Creates a Signal which uses a closure to asynchronously transform the value.

When the output Signal is spawned:

  1. It calls the closure with the current value of self.

  2. The closure returns a Future. It waits for that Future to finish, and then it puts the return value of the Future into the output Signal.

  3. Whenever self changes it repeats the above steps.

It will call the closure at most once for each change in self.

Because Signals must always have a current value, if the Future is not ready yet, then the output Signal will start with the value None. When the Future finishes it then changes to Some. This can be used to detect whether the Future has finished or not.

If self changes before the old Future is finished, it will cancel the old Future. That means if self changes faster than the Future, then it will never output any values.

Like all of the Signal methods, map_future might skip intermediate changes. So you cannot rely upon the closure being called for every intermediate change. But you can rely upon it always being called with the most recent change.

Examples

Call an asynchronous network API whenever the input changes:

let mapped = input.map_future(|value| call_network_api(value));

Performance

This is extremely efficient: it does not do any heap allocation, and it has very little overhead.

Of course the performance will also depend upon the Future which is returned from the closure.

Creates a Signal which uses a closure to filter and transform the value.

When the output Signal is spawned:

  1. The output Signal starts with the value None.

  2. It calls the closure with the current value of self.

  3. If the closure returns Some, then it puts the return value of the closure into the output Signal.

  4. If the closure returns None, then it does nothing.

  5. Whenever self changes it repeats steps 2 - 4.

The output Signal will only be None for the initial value. After that it will always be Some.

If the closure returns Some for the initial value, then the output Signal will never be None.

It will call the closure at most once for each change in self.

Like all of the Signal methods, filter_map might skip intermediate changes. So you cannot rely upon the closure being called for every intermediate change. But you can rely upon it always being called with the most recent change.

Examples

Add 1 to the value, but only if the value is less than 5:

let mapped = input.filter_map(|value| {
    if value < 5 {
        Some(value + 1)

    } else {
        None
    }
});

If the initial value of input is 5 or greater then mapped will be None.

If the current value of input is 5 or greater then mapped will keep its old value.

Otherwise mapped will be Some(input + 1).

Performance

This is extremely efficient: it does not do any heap allocation, and it has very little overhead.

Creates a Signal which delays updates until a Future finishes.

This can be used to throttle a Signal so that it only updates once every X seconds.

If multiple updates happen while it’s being delayed, it will only output the most recent value.

Examples

Wait 1 second between each update:

let output = input.throttle(|| sleep(1_000));

Performance

This is extremely efficient: it does not do any heap allocation, and it has very little overhead.

Creates a Signal which flattens self.

When the output Signal is spawned:

  1. It retrieves the current value of self (this value is also a Signal).

  2. Then it puts the current value of the inner Signal into the output Signal.

  3. Whenever the inner Signal changes it puts the new value into the output Signal.

  4. Whenever self changes it repeats the above steps.

    This happens automatically and efficiently.

Like all of the Signal methods, flatten might skip intermediate changes. So you cannot rely upon it containing every intermediate change. But you can rely upon it always containing the most recent change.

Performance

This is very efficient: it is guaranteed constant time, and it does not do any heap allocation.

A convenience for calling Signal::poll_change on Unpin types.

Implementors