use crate::compat::Duration;
use core::future::Future;
pub trait Sleeper {
type Sleep: Future<Output = ()>;
fn sleep(&self, dur: Duration) -> Self::Sleep;
}
impl<F, Fut> Sleeper for F
where
F: Fn(Duration) -> Fut,
Fut: Future<Output = ()>,
{
type Sleep = Fut;
fn sleep(&self, dur: Duration) -> Self::Sleep {
(self)(dur)
}
}
#[cfg(feature = "tokio-sleep")]
#[must_use]
pub fn tokio() -> fn(Duration) -> tokio::time::Sleep {
tokio::time::sleep
}
#[cfg(all(feature = "gloo-timers-sleep", target_arch = "wasm32"))]
#[must_use]
pub fn gloo() -> fn(Duration) -> gloo_timers::future::TimeoutFuture {
gloo_timers::future::sleep
}
#[cfg(feature = "futures-timer-sleep")]
#[must_use]
pub fn futures_timer() -> fn(Duration) -> futures_timer::Delay {
futures_timer::Delay::new
}
#[cfg(feature = "embassy-sleep")]
#[must_use]
pub fn embassy() -> fn(Duration) -> embassy_time::Timer {
embassy_sleep_fn
}
#[cfg(feature = "embassy-sleep")]
fn embassy_sleep_fn(dur: Duration) -> embassy_time::Timer {
embassy_time::Timer::after(to_embassy_duration(dur))
}
#[cfg(feature = "embassy-sleep")]
fn to_embassy_duration(dur: Duration) -> embassy_time::Duration {
const MICROS_PER_SEC: u128 = 1_000_000;
let ticks_ceil = dur
.as_micros()
.saturating_mul(u128::from(embassy_time::TICK_HZ))
.div_ceil(MICROS_PER_SEC);
let ticks = u64::try_from(ticks_ceil).unwrap_or(u64::MAX);
embassy_time::Duration::from_ticks(ticks)
}
#[cfg(all(test, feature = "embassy-sleep"))]
mod tests {
use super::to_embassy_duration;
use crate::compat::Duration;
const ARBITRARY_MICROS: u64 = 1_500;
#[test]
fn to_embassy_duration_preserves_micros() {
assert_eq!(
to_embassy_duration(Duration::from_micros(ARBITRARY_MICROS)),
embassy_time::Duration::from_micros(ARBITRARY_MICROS)
);
}
#[test]
fn to_embassy_duration_saturates_at_embassy_max() {
assert_eq!(
to_embassy_duration(Duration::MAX),
embassy_time::Duration::MAX
);
}
proptest::proptest! {
#[test]
fn to_embassy_duration_never_panics(secs in proptest::prelude::any::<u64>(), nanos in 0..1_000_000_000_u32) {
let _ = to_embassy_duration(Duration::new(secs, nanos));
}
}
}