[][src]Function sunrise_libutils::loop_future::loop_fn

pub fn loop_fn<S, T, A, F>(initial_state: S, func: F) -> LoopFn<A, F> where
    F: FnMut(S) -> A,
    A: Future<Output = Loop<T, S>> + Unpin

Creates a new future implementing a tail-recursive loop.

The loop function is immediately called with initial_state and should return a value that can be converted to a future. On successful completion, this future should output a Loop<T, S> to indicate the status of the loop.

Loop::Break(T) halts the loop and completes the future with output T.

Loop::Continue(S) reinvokes the loop function with state S. The returned future will be subsequently polled for a new Loop<T, S> value.

Examples

use sunrise_libutils::loop_future::{loop_fn, Loop};
use core::future::Future;
use futures::future::{FutureExt, ready};

struct Client {
    ping_count: u8,
}

impl Client {
    fn new() -> Self {
        Client { ping_count: 0 }
    }

    fn send_ping(self) -> impl Future<Output=Self> {
        ready(Client { ping_count: self.ping_count + 1 })
    }

    fn receive_pong(self) -> impl Future<Output=(Self, bool)> {
        let done = self.ping_count >= 5;
        ready((self, done))
    }
}

let ping_til_done = loop_fn(Client::new(), |client| {
    client.send_ping()
        .then(|client| client.receive_pong())
        .map(|(client, done)| {
            if done {
                Loop::Break(client)
            } else {
                Loop::Continue(client)
            }
        })
});