rings-core 0.20.0

Chord DHT implementation with ICE
Documentation
use std::future::Future;
use std::time::Duration;

use futures::FutureExt;

use crate::utils::try_sleep;

pub(super) enum InboundDeadline<T> {
    Completed(T),
    TimedOut,
    TimerUnavailable,
}

pub(super) async fn await_inbound_deadline<F, T>(
    future: F,
    timeout: Duration,
) -> InboundDeadline<T>
where
    F: Future<Output = T>,
{
    await_inbound_deadline_with_timer(future, try_sleep(timeout)).await
}

async fn await_inbound_deadline_with_timer<F, T, D>(future: F, deadline: D) -> InboundDeadline<T>
where
    F: Future<Output = T>,
    D: Future<Output = bool>,
{
    let future = future.fuse();
    let deadline = deadline.fuse();
    futures::pin_mut!(future, deadline);
    futures::select! {
        output = future => InboundDeadline::Completed(output),
        completed = deadline => if completed {
            InboundDeadline::TimedOut
        } else {
            InboundDeadline::TimerUnavailable
        },
    }
}

#[cfg(all(test, not(target_family = "wasm")))]
mod tests {
    use super::*;

    #[tokio::test]
    async fn rejected_timer_fails_closed_without_polling_forever() {
        let outcome = await_inbound_deadline_with_timer(
            futures::future::pending::<()>(),
            futures::future::ready(false),
        )
        .await;
        assert!(matches!(outcome, InboundDeadline::TimerUnavailable));
    }
}