use crate::break_apart::BreakApart;
use crate::messaging;
use crate::messaging::{IntoMultiSender, IntoSender};
use crate::test_loop::futures::{
TestLoopAsyncComputationEvent, TestLoopAsyncComputationSpawner, TestLoopDelayedActionEvent,
TestLoopDelayedActionRunner,
};
use near_time::Duration;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use super::futures::{TestLoopFutureSpawner, TestLoopTask};
pub struct DelaySender<Event>(Arc<dyn Fn(Event, time::Duration) + Send + Sync>);
impl<Message, Event: From<Message> + 'static> messaging::CanSend<Message> for DelaySender<Event> {
fn send(&self, message: Message) {
self.send_with_delay(message.into(), time::Duration::ZERO);
}
}
impl<Event> DelaySender<Event> {
pub fn new(inner: impl Fn(Event, time::Duration) + Send + Sync + 'static) -> Self {
Self(Arc::new(inner))
}
pub fn send_with_delay(&self, event: Event, delay: time::Duration) {
self.0(event, delay);
}
pub fn with_additional_delay(&self, delay: time::Duration) -> DelaySender<Event>
where
Event: 'static,
{
let f = self.0.clone();
Self(Arc::new(move |event, other_delay| f(event, delay + other_delay)))
}
pub fn narrow<InnerEvent>(self) -> DelaySender<InnerEvent>
where
Event: From<InnerEvent> + 'static,
{
DelaySender::<InnerEvent>::new(move |event, delay| {
self.send_with_delay(event.into(), delay)
})
}
pub fn into_wrapped_multi_sender<M: 'static, S: 'static>(self) -> S
where
Self: IntoSender<M>,
BreakApart<M>: IntoMultiSender<S>,
{
self.into_sender().break_apart().into_multi_sender()
}
pub fn into_delayed_action_runner<InnerData>(
self,
shutting_down: Arc<AtomicBool>,
) -> TestLoopDelayedActionRunner<InnerData>
where
Event: From<TestLoopDelayedActionEvent<InnerData>> + 'static,
{
TestLoopDelayedActionRunner { sender: self.narrow(), shutting_down }
}
pub fn into_future_spawner(self) -> TestLoopFutureSpawner
where
Event: From<Arc<TestLoopTask>> + 'static,
{
self.narrow()
}
pub fn into_async_computation_spawner(
self,
artificial_delay: impl Fn(&str) -> Duration + Send + Sync + 'static,
) -> TestLoopAsyncComputationSpawner
where
Event: From<TestLoopAsyncComputationEvent> + 'static,
{
TestLoopAsyncComputationSpawner {
sender: self.narrow(),
artificial_delay: Box::new(artificial_delay),
}
}
}
impl<Event: 'static> DelaySender<(usize, Event)> {
pub fn for_index(self, index: usize) -> DelaySender<Event> {
DelaySender::new(move |event, delay| {
self.send_with_delay((index, event), delay);
})
}
}
impl<Event> Clone for DelaySender<Event> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}