1use std::fmt::Debug;
2use std::future::Future;
3use std::pin::Pin;
4use std::sync::{Arc, Mutex};
5use std::task::{Context, Poll};
6use thiserror::Error;
7use tokio::sync::mpsc::{self, Receiver, Sender};
8
9#[derive(Error, Debug)]
10pub enum PromiseError {
11 #[error("error: {0}")]
12 PromiseResolve(String),
13 #[error("error: {0}")]
14 PromiseReject(String),
15 #[error("Promise error")]
16 Unknown,
17}
18
19#[derive(Debug)]
20pub enum PromiseResult<T> {
21 Resolved(T),
22 Rejected(T),
23}
24
25unsafe impl<T: Send> Send for PromiseResult<T> {}
26unsafe impl<T: Sync> Sync for PromiseResult<T> {}
27
28#[derive(Debug, Clone)]
29pub struct Promise<T: Send + Sync>(
30 Sender<PromiseResult<T>>,
31 Arc<Mutex<Receiver<PromiseResult<T>>>>,
32);
33
34unsafe impl<T: Send + Sync> Send for Promise<T> {}
35unsafe impl<T: Send + Sync> Sync for Promise<T> {}
36impl<T: Send + Sync> Unpin for Promise<T> {}
37
38impl<T: Send + Sync + Debug> Promise<T> {
39 pub fn new() -> Self {
40 let (sender, receiver) = mpsc::channel(1);
41 Promise(sender, Arc::new(Mutex::new(receiver)))
42 }
43
44 pub async fn resolve(&mut self, value: T) -> Result<(), PromiseError> {
45 self.0
46 .send(PromiseResult::Resolved(value))
47 .await
48 .or_else(|error| Err(PromiseError::PromiseResolve(error.to_string())))
49 }
50
51 pub async fn reject(&mut self, value: T) -> Result<(), PromiseError> {
52 self.0
53 .send(PromiseResult::Rejected(value))
54 .await
55 .or_else(|error| Err(PromiseError::PromiseReject(error.to_string())))
56 }
57}
58
59impl<T: Send + Sync + Clone> Future for Promise<T> {
60 type Output = PromiseResult<T>;
61
62 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
63 match self.1.lock().unwrap().try_recv() {
64 Ok(value) => Poll::Ready(value),
65 Err(_) => {
66 cx.waker().wake_by_ref();
67 Poll::Pending
68 }
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[tokio::test]
78 async fn test() {
79 let promise = Promise::<String>::new();
80 let mut promise_clone = promise.clone();
81 let send_data = "111";
82 tokio::spawn(async move {
83 promise_clone.resolve(send_data.to_string()).await.unwrap();
84 promise_clone.reject(send_data.to_string()).await.unwrap();
85 });
86
87 if let PromiseResult::Resolved(value) = promise.clone().await {
88 assert_eq!(value, send_data);
89 } else {
90 panic!("error");
91 }
92
93 if let PromiseResult::Rejected(value) = promise.clone().await {
94 assert_eq!(value, send_data);
95 } else {
96 panic!("error");
97 }
98 }
99}