1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll};
use thiserror::Error;
use tokio::sync::mpsc::{self, Receiver, Sender};

#[derive(Error, Debug)]
pub enum PromiseError {
    #[error("error: {0}")]
    PromiseResolve(String),
    #[error("error: {0}")]
    PromiseReject(String),
    #[error("Promise error")]
    Unknown,
}

#[derive(Debug)]
pub enum PromiseResult<T> {
    Resolved(T),
    Rejected(T),
}

unsafe impl<T: Send> Send for PromiseResult<T> {}
unsafe impl<T: Sync> Sync for PromiseResult<T> {}

#[derive(Debug, Clone)]
pub struct Promise<T: Send + Sync>(
    Sender<PromiseResult<T>>,
    Arc<Mutex<Receiver<PromiseResult<T>>>>,
);

unsafe impl<T: Send + Sync> Send for Promise<T> {}
unsafe impl<T: Send + Sync> Sync for Promise<T> {}
impl<T: Send + Sync> Unpin for Promise<T> {}

impl<T: Send + Sync + Debug> Promise<T> {
    pub fn new() -> Self {
        let (sender, receiver) = mpsc::channel(1);
        Promise(sender, Arc::new(Mutex::new(receiver)))
    }

    pub async fn resolve(&mut self, value: T) -> Result<(), PromiseError> {
        self.0
            .send(PromiseResult::Resolved(value))
            .await
            .or_else(|error| Err(PromiseError::PromiseResolve(error.to_string())))
    }

    pub async fn reject(&mut self, value: T) -> Result<(), PromiseError> {
        self.0
            .send(PromiseResult::Rejected(value))
            .await
            .or_else(|error| Err(PromiseError::PromiseReject(error.to_string())))
    }
}

impl<T: Send + Sync + Clone> Future for Promise<T> {
    type Output = PromiseResult<T>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match self.1.lock().unwrap().try_recv() {
            Ok(value) => Poll::Ready(value),
            Err(_) => {
                cx.waker().wake_by_ref();
                Poll::Pending
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test() {
        let promise = Promise::<String>::new();
        let mut promise_clone = promise.clone();
        let send_data = "111";
        tokio::spawn(async move {
            promise_clone.resolve(send_data.to_string()).await.unwrap();
            promise_clone.reject(send_data.to_string()).await.unwrap();
        });

        if let PromiseResult::Resolved(value) = promise.clone().await {
            assert_eq!(value, send_data);
        } else {
            panic!("error");
        }

        if let PromiseResult::Rejected(value) = promise.clone().await {
            assert_eq!(value, send_data);
        } else {
            panic!("error");
        }
    }
}