use crate::TaskHandlerId; use std::cmp::Ordering; use tokio::sync::oneshot::{Receiver, Sender}; #[derive(Eq, Debug, Clone, Copy)] pub enum QualityOfService { Background, UserInteractive, } impl PartialEq for QualityOfService { fn eq(&self, other: &Self) -> bool { matches!( (self, other), (Self::Background, Self::Background) | (Self::UserInteractive, Self::UserInteractive) ) } } pub type TaskId = u32; #[derive(Eq, Debug, Clone, Copy)] pub struct PendingTask { pub qos: QualityOfService, pub id: TaskId, } impl PartialEq for PendingTask { fn eq(&self, other: &Self) -> bool { self.id.eq(&other.id) } } impl PartialOrd for PendingTask { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for PendingTask { fn cmp(&self, other: &Self) -> Ordering { match (self.qos, other.qos) { // User interactive (QualityOfService::UserInteractive, QualityOfService::UserInteractive) => self.id.cmp(&other.id), (QualityOfService::UserInteractive, _) => Ordering::Greater, (_, QualityOfService::UserInteractive) => Ordering::Less, // background (QualityOfService::Background, QualityOfService::Background) => self.id.cmp(&other.id), } } } #[derive(Debug, Clone)] pub enum TaskContent { Text(String), Blob(Vec), } #[derive(Debug, Eq, PartialEq, Clone)] pub enum TaskState { Pending, Processing, Done, Failure, Cancel, Timeout, } impl TaskState { pub fn is_pending(&self) -> bool { matches!(self, TaskState::Pending) } pub fn is_done(&self) -> bool { matches!(self, TaskState::Done) } pub fn is_cancel(&self) -> bool { matches!(self, TaskState::Cancel) } pub fn is_processing(&self) -> bool { matches!(self, TaskState::Processing) } pub fn is_failed(&self) -> bool { matches!(self, TaskState::Failure) } } pub struct Task { pub id: TaskId, pub handler_id: TaskHandlerId, pub content: Option, pub qos: QualityOfService, state: TaskState, pub ret: Option>, pub recv: Option>, } impl Task { pub fn background(handler_id: &str, id: TaskId, content: TaskContent) -> Self { Self::new(handler_id, id, content, QualityOfService::Background) } pub fn user_interactive(handler_id: &str, id: TaskId, content: TaskContent) -> Self { Self::new(handler_id, id, content, QualityOfService::UserInteractive) } pub fn new(handler_id: &str, id: TaskId, content: TaskContent, qos: QualityOfService) -> Self { let handler_id = handler_id.to_owned(); let (ret, recv) = tokio::sync::oneshot::channel(); Self { handler_id, id, content: Some(content), qos, ret: Some(ret), recv: Some(recv), state: TaskState::Pending, } } pub fn state(&self) -> &TaskState { &self.state } pub(crate) fn set_state(&mut self, status: TaskState) { self.state = status; } } pub struct TaskResult { pub id: TaskId, pub state: TaskState, } impl std::convert::From for TaskResult { fn from(task: Task) -> Self { TaskResult { id: task.id, state: task.state().clone(), } } }