use std::{pin::Pin, time::Duration};
use tokio::sync::oneshot::Sender;
use crate::prelude::*;
#[derive(Debug)]
pub(crate) enum SpecialTask {
None,
Stop,
ResetState,
}
pub(crate) enum TaskHandle<Message> {
Simple(Pin<Box<dyn Future<Output = Result<Message>> + Send + Sync + 'static>>),
Batch(Vec<Task<Message>>),
Then(Box<Task<Message>>, Box<Task<Message>>),
Special(SpecialTask),
}
pub struct Task<Message> {
pub(crate) handle: TaskHandle<Message>,
pub(crate) signal: Option<Sender<()>>,
}
impl<Message: Sync + Send + 'static> Task<Message> {
pub fn new(fut: impl Future<Output = Result<Message>> + Send + Sync + 'static) -> Self {
Task {
handle: TaskHandle::Simple(Box::pin(fut)),
signal: None,
}
}
pub fn batch(self, other: Task<Message>) -> Self {
Task {
handle: TaskHandle::Batch(vec![self, other]),
signal: None,
}
}
pub fn then(self, next: Task<Message>) -> Self {
Task {
handle: TaskHandle::Then(Box::new(self), Box::new(next)),
signal: None,
}
}
pub fn stop() -> Self {
Task {
handle: TaskHandle::Special(SpecialTask::Stop),
signal: None,
}
}
pub fn none() -> Self {
Task {
handle: TaskHandle::Special(SpecialTask::None),
signal: None,
}
}
pub fn wait(duration: Duration, message: Message) -> Self {
Task {
handle: TaskHandle::Simple(Box::pin(async move {
tokio::time::sleep(duration).await;
Ok(message)
})),
signal: None,
}
}
pub fn reset_state() -> Self {
Task {
handle: TaskHandle::Special(SpecialTask::ResetState),
signal: None,
}
}
pub fn msg(message: Message) -> Self {
Task {
handle: TaskHandle::Simple(Box::pin(async move { Ok(message) })),
signal: None,
}
}
}