1use crate::prelude::*;
10use crate::string::SharedString;
11use crate::task;
12
13pub type Index = usize;
15
16#[derive(Deref, DerefMut)]
19pub struct TryJoin<T, E> {
20 #[deref]
21 #[deref_mut]
22 join: task::Join<Result<T, E>>,
23}
24
25impl<T, E> TryJoin<T, E>
26where
27 T: Send + 'static,
28 E: From<task::Panic> + Send + 'static,
29{
30 pub fn new() -> Self {
32 Self { join: task::Join::new() }
33 }
34
35 pub fn add(&mut self, task: impl task::Start<Result<T, E>>) -> Index {
37 self.join.add(task)
38 }
39
40 pub fn add_as(
42 &mut self,
43 name: impl Into<SharedString>,
44 task: impl task::Start<Result<T, E>>,
45 ) -> Index {
46 self.join.add_as(name, task)
47 }
48
49 pub async fn next(&mut self) -> Option<StoppedTask<T, E>> {
53 let task = self.join.next().await?;
54
55 Some(StoppedTask {
56 index: task.index,
57 name: task.name,
58 result: task.result.map_err(E::from).and_then(|res| res),
59 })
60 }
61
62 pub async fn try_next(&mut self) -> Option<Result<FinishedTask<T>, FailedTask<E>>> {
67 let task = self.next().await?;
68
69 Some(match task.result {
70 Ok(output) => Ok(FinishedTask { index: task.index, name: task.name, output }),
71 Err(error) => Err(FailedTask { index: task.index, name: task.name, error }),
72 })
73 }
74
75 pub async fn drain(&mut self) {
77 self.join.drain().await
78 }
79
80 pub async fn try_drain(&mut self) -> Result<(), FailedTask<E>> {
82 while self.try_next().await.transpose()?.is_some() {}
83
84 Ok(())
85 }
86}
87
88impl<T, E> Default for TryJoin<T, E>
89where
90 T: Send + 'static,
91 E: From<Panic> + Send + 'static,
92{
93 fn default() -> Self {
94 Self::new()
95 }
96}
97
98#[derive(Debug)]
100pub struct StoppedTask<T, E> {
101 pub index: Index,
103 pub name: SharedString,
105 pub result: Result<T, E>,
107}
108
109#[derive(Debug)]
111pub struct FinishedTask<T> {
112 pub index: Index,
114 pub name: SharedString,
116 pub output: T,
118}
119
120#[derive(Debug)]
122pub struct FailedTask<E> {
123 pub index: Index,
125 pub name: SharedString,
127 pub error: E,
129}
130
131impl<E> Display for FailedTask<E>
132where
133 E: Display,
134{
135 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
136 match self.name.as_str() {
137 "" => write!(f, "Task #{} ", self.index)?,
138 name => write!(f, "Task `{}`", name)?,
139 }
140
141 write!(f, "failed. {}", self.error)
142 }
143}
144
145impl<E> Error for FailedTask<E> where E: Debug + Display {}