deft 0.15.0

Cross platform ui framework
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll, Waker};

#[derive(Clone)]
struct PromiseInner<T, E> {
    value: Option<Result<T, E>>,
    waker: Option<Waker>,
}
#[derive(Clone)]
pub struct Promise<T, E> {
    inner: Arc<Mutex<PromiseInner<T, E>>>,
}

impl<T, E> Promise<T, E> {
    pub fn new() -> Self {
        let inner: PromiseInner<T, E> = PromiseInner {
            value: None,
            waker: None,
        };
        Promise {
            inner: Arc::new(Mutex::new(inner)),
        }
    }

    pub fn new_resolved(value: T) -> Self {
        let p = Self::new();
        p.resolve(value);
        p
    }

    pub fn new_rejected(err: E) -> Self {
        let p = Self::new();
        p.reject(err);
        p
    }

    pub fn resolve(&self, value: T) {
        self.set_value(Ok(value));
    }

    pub fn reject(&self, err: E) {
        self.set_value(Err(err));
    }

    fn set_value(&self, result: Result<T, E>) {
        let mut inner = self.inner.lock().unwrap();
        if inner.value.is_some() {
            return;
        }
        inner.value = Some(result);
        if let Some(wk) = &inner.waker {
            wk.clone().wake();
        }
    }
}

impl<T, E> Future for Promise<T, E>
where
    T: Clone,
    E: Clone,
{
    type Output = Result<T, E>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut inner = self.inner.lock().unwrap();
        return if let Some(result) = &inner.value {
            match result {
                Ok(v) => Poll::Ready(Ok(v.clone())),
                Err(e) => Poll::Ready(Err(e.clone())),
            }
        } else {
            inner.waker = Some(cx.waker().clone());
            Poll::Pending
        };
    }
}