jay-compositor 1.15.0

The Jay compositor
use crate::utils::markers::JayClone;
use crate::utils::ptr_ext::MutPtrExt;
use crate::utils::ptr_ext::PtrExt;
use derivative::Derivative;
use std::cell::Cell;
use std::cell::UnsafeCell;
use std::mem;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
use std::task::Waker;

#[derive(Derivative)]
#[derivative(Default(bound = ""))]
pub struct Stack<T> {
    vec: UnsafeCell<Vec<T>>,
}

impl<T> Stack<T> {
    pub const fn new() -> Stack<T> {
        Self {
            vec: UnsafeCell::new(vec![]),
        }
    }

    pub fn push(&self, v: T) {
        unsafe {
            self.vec.get().deref_mut().push(v);
        }
    }

    pub fn pop(&self) -> Option<T> {
        unsafe { self.vec.get().deref_mut().pop() }
    }

    pub fn to_vec(&self) -> Vec<T>
    where
        T: JayClone,
    {
        unsafe {
            let v = self.vec.get().deref();
            (*v).clone()
        }
    }

    pub fn take(&self) -> Vec<T> {
        unsafe { mem::take(self.vec.get().deref_mut()) }
    }

    pub fn len(&self) -> usize {
        unsafe { self.vec.get().deref().len() }
    }

    pub fn swap(&self, vec: &mut Vec<T>) {
        unsafe { mem::swap(self.vec.get().deref_mut(), vec) }
    }

    fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn clear(&self) {
        let mut vec = vec![];
        self.swap(&mut vec);
        vec.clear();
        if self.is_empty() {
            self.swap(&mut vec);
        }
    }
}

#[derive(Derivative)]
#[derivative(Default(bound = ""))]
pub struct AsyncStack<T> {
    stack: Stack<T>,
    waiter: Cell<Option<Waker>>,
}

impl<T> AsyncStack<T> {
    pub fn push(&self, v: T) {
        self.stack.push(v);
        if let Some(waker) = self.waiter.take() {
            waker.wake();
        }
    }

    pub fn non_empty(&self) -> AsyncStackNonEmpty<'_, T> {
        AsyncStackNonEmpty { stack: self }
    }

    pub fn swap(&self, vec: &mut Vec<T>) {
        self.stack.swap(vec);
    }

    pub fn clear(&self) {
        self.waiter.take();
        self.stack.take();
    }
}

pub struct AsyncStackNonEmpty<'a, T> {
    stack: &'a AsyncStack<T>,
}

impl<T> Future for AsyncStackNonEmpty<'_, T> {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        if self.stack.stack.len() > 0 {
            Poll::Ready(())
        } else {
            self.stack.waiter.set(Some(cx.waker().clone()));
            Poll::Pending
        }
    }
}