simulate_promise/
lib.rs

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}