use std::future::Future;
use std::time::Duration;
use tokio::time::{MissedTickBehavior, interval};
use crate::RoplatError;
use crate::rhythm::Rhythm;
impl<I> Rhythm for I
where
I: Iterator + Send, I::Item: Send, {
type Yield = I::Item;
type Feed = ();
type Output = ();
type Error = RoplatError;
async fn drive<N, F, Fut>(
&mut self,
mut nodes: N,
mut op_domain: F,
) -> (Self::Output, N)
where
N: Send,
F: FnMut(N, Self::Yield) -> Fut + Send,
Fut: Future<Output = (Self::Feed, N)> + Send,
{
for item in self {
let ((), returned_nodes) = op_domain(nodes, item).await;
nodes = returned_nodes;
tokio::task::yield_now().await;
}
((), nodes)
}
}
pub trait WithPeriod: Sized {
type WithPeriod;
fn with_period(self, period: Duration) -> Self::WithPeriod;
}
impl<I: Iterator> WithPeriod for I {
type WithPeriod = IterWithPeriod<I>;
fn with_period(self, period: Duration) -> Self::WithPeriod {
IterWithPeriod::new(self, period)
}
}
pub struct IterWithPeriod<I> {
iter: I,
period: Duration,
}
impl<I> IterWithPeriod<I> {
pub fn new(iter: I, period: Duration) -> Self {
Self { iter, period }
}
pub fn with_missed_tick_behavior(self, _behavior: MissedTickBehavior) -> Self {
self
}
}
impl<I> Rhythm for IterWithPeriod<I>
where
I: Iterator + Send,
I::Item: Send,
{
type Yield = I::Item;
type Feed = ();
type Output = ();
type Error = RoplatError;
async fn drive<N, F, Fut>(
&mut self,
mut nodes: N,
mut op_domain: F,
) -> (Self::Output, N)
where
N: Send,
F: FnMut(N, Self::Yield) -> Fut + Send,
Fut: Future<Output = (Self::Feed, N)> + Send,
{
let mut timer = interval(self.period);
timer.set_missed_tick_behavior(MissedTickBehavior::Skip);
for item in &mut self.iter {
timer.tick().await;
let ((), returned_nodes) = op_domain(nodes, item).await;
nodes = returned_nodes;
}
((), nodes)
}
}