ux-dx 0.2.1

3D Graphics Primitives for Angular Rust
Documentation
//! Main futures
use std::{
    cell::RefCell,
    future::Future,
    pin::Pin,
    task::{Context, Poll},
    time::Instant,
};
use winit::{
    event::{Event, StartCause},
    event_loop::ControlFlow,
    window::WindowId,
};

use super::{EventAsync, SharedState, WaitCanceledCause};

#[must_use]
pub struct WaitFuture<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
}

#[must_use]
pub struct WaitUntilFuture<'a, E: 'static> {
    pub(crate) timeout: Instant,
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
}

#[must_use]
pub(crate) struct EventReceiverBuilder<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
}

pub struct EventReceiver<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
}

#[must_use]
pub struct PollFuture<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
    pub(crate) sealed: bool,
}

#[must_use]
pub(crate) struct RedrawRequestReceiverBuilder<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
}

pub struct RedrawRequestReceiver<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
}

#[must_use]
pub struct RedrawRequestFuture<'a, E: 'static> {
    pub(crate) shared_state: &'a RefCell<SharedState<E>>,
    pub(crate) sealed: bool,
}

impl<E> Future for WaitFuture<'_, E> {
    type Output = ();

    fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<()> {
        let mut shared_state = self.shared_state.borrow_mut();
        match shared_state.next_event {
            Some(Event::NewEvents { .. }) => {
                unsafe { *shared_state.control_flow.unwrap().as_mut() = ControlFlow::Poll };
                Poll::Ready(())
            }
            Some(Event::RedrawEventsCleared) => {
                unsafe { *shared_state.control_flow.unwrap().as_mut() = ControlFlow::Wait };
                shared_state.next_event = None;
                Poll::Pending
            }
            Some(Event::WindowEvent { .. })
            | Some(Event::DeviceEvent { .. })
            | Some(Event::UserEvent { .. })
            | Some(Event::MainEventsCleared)
            | Some(Event::RedrawRequested { .. }) => {
                shared_state.next_event = None;
                Poll::Pending
            }
            Some(Event::LoopDestroyed) => unreachable!(),
            Some(Event::Suspended) | Some(Event::Resumed) => unimplemented!(),
            None => Poll::Pending,
        }
    }
}

impl<E> Future for WaitUntilFuture<'_, E> {
    type Output = WaitCanceledCause;

    fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<WaitCanceledCause> {
        let mut shared_state = self.shared_state.borrow_mut();
        match shared_state.next_event {
            Some(Event::NewEvents(cause)) => {
                unsafe { *shared_state.control_flow.unwrap().as_mut() = ControlFlow::Poll };
                Poll::Ready(match cause {
                    StartCause::ResumeTimeReached { .. } => WaitCanceledCause::ResumeTimeReached,
                    StartCause::WaitCancelled { .. } | StartCause::Poll | StartCause::Init => {
                        WaitCanceledCause::EventsReceived
                    }
                })
            }
            Some(Event::RedrawEventsCleared) => {
                unsafe {
                    *shared_state.control_flow.unwrap().as_mut() =
                        ControlFlow::WaitUntil(self.timeout)
                };
                shared_state.next_event = None;
                Poll::Pending
            }
            Some(Event::WindowEvent { .. })
            | Some(Event::DeviceEvent { .. })
            | Some(Event::UserEvent { .. })
            | Some(Event::MainEventsCleared)
            | Some(Event::RedrawRequested { .. }) => {
                shared_state.next_event = None;
                Poll::Pending
            }
            Some(Event::LoopDestroyed) => unreachable!(),
            Some(Event::Suspended) | Some(Event::Resumed) => unimplemented!(),
            None => Poll::Pending,
        }
    }
}

impl<'el, E> Future for EventReceiverBuilder<'el, E> {
    type Output = EventReceiver<'el, E>;
    fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<EventReceiver<'el, E>> {
        let mut shared_state = self.shared_state.borrow_mut();
        match shared_state.next_event {
            Some(Event::RedrawRequested { .. })
            | Some(Event::RedrawEventsCleared)
            | Some(Event::MainEventsCleared) => {
                shared_state.next_event = None;
                Poll::Pending
            }
            Some(Event::NewEvents(_)) => {
                shared_state.next_event = None;
                Poll::Ready(EventReceiver {
                    shared_state: self.shared_state,
                })
            }
            Some(Event::WindowEvent { .. })
            | Some(Event::DeviceEvent { .. })
            | Some(Event::UserEvent { .. })
            | Some(Event::LoopDestroyed) => unreachable!(),
            Some(Event::Suspended) | Some(Event::Resumed) => unimplemented!(),
            None => Poll::Pending,
        }
    }
}

impl<'el, E> EventReceiver<'el, E> {
    pub fn next(&mut self) -> PollFuture<'_, E> {
        PollFuture {
            shared_state: &self.shared_state,
            sealed: false,
        }
    }

    pub fn redraw_requests(self) -> impl Future<Output = RedrawRequestReceiver<'el, E>> {
        RedrawRequestReceiverBuilder {
            shared_state: &self.shared_state,
        }
    }
}

impl<E> Future for PollFuture<'_, E> {
    type Output = Option<EventAsync<E>>;

    fn poll(mut self: Pin<&mut Self>, _: &mut Context) -> Poll<Option<EventAsync<E>>> {
        if self.sealed {
            return Poll::Ready(None);
        }

        let mut shared_state = self.shared_state.borrow_mut();
        match shared_state.next_event.take() {
            Some(Event::WindowEvent { window_id, event }) => {
                Poll::Ready(Some(EventAsync::WindowEvent { window_id, event }))
            }
            Some(Event::DeviceEvent { device_id, event }) => {
                Poll::Ready(Some(EventAsync::DeviceEvent { device_id, event }))
            }
            Some(Event::UserEvent(event)) => Poll::Ready(Some(EventAsync::UserEvent(event))),
            Some(Event::MainEventsCleared) => {
                self.sealed = true;
                Poll::Ready(None)
            }
            event @ Some(Event::RedrawRequested { .. })
            | event @ Some(Event::RedrawEventsCleared) => {
                shared_state.next_event = event;
                Poll::Ready(None)
            }
            Some(Event::NewEvents(_)) | Some(Event::LoopDestroyed) => unreachable!(),
            Some(Event::Suspended) | Some(Event::Resumed) => unimplemented!(),
            None => Poll::Pending,
        }
    }
}

impl<'el, E> Future for RedrawRequestReceiverBuilder<'el, E> {
    type Output = RedrawRequestReceiver<'el, E>;
    fn poll(self: Pin<&mut Self>, _: &mut Context) -> Poll<RedrawRequestReceiver<'el, E>> {
        let mut shared_state = self.shared_state.borrow_mut();
        match shared_state.next_event {
            Some(Event::RedrawRequested { .. }) | Some(Event::RedrawEventsCleared) => {
                Poll::Ready(RedrawRequestReceiver {
                    shared_state: self.shared_state,
                })
            }
            Some(Event::MainEventsCleared)
            | Some(Event::WindowEvent { .. })
            | Some(Event::DeviceEvent { .. })
            | Some(Event::UserEvent { .. }) => {
                shared_state.next_event = None;
                Poll::Pending
            }
            Some(Event::NewEvents { .. }) | Some(Event::LoopDestroyed) => unreachable!(),
            Some(Event::Suspended) | Some(Event::Resumed) => unimplemented!(),
            None => Poll::Pending,
        }
    }
}

impl<'el, E> RedrawRequestReceiver<'el, E> {
    pub fn next(&mut self) -> RedrawRequestFuture<'_, E> {
        RedrawRequestFuture {
            shared_state: &self.shared_state,
            sealed: false,
        }
    }
}

impl<'el, E> Future for RedrawRequestFuture<'el, E> {
    type Output = Option<WindowId>;

    fn poll(mut self: Pin<&mut Self>, _: &mut Context) -> Poll<Option<WindowId>> {
        if self.sealed {
            return Poll::Ready(None);
        }

        let mut shared_state = self.shared_state.borrow_mut();
        match shared_state.next_event {
            Some(Event::RedrawRequested(window_id)) => {
                shared_state.next_event = None;
                Poll::Ready(Some(window_id))
            }
            Some(Event::RedrawEventsCleared) => {
                self.sealed = true;
                Poll::Ready(None)
            }
            Some(Event::WindowEvent { .. })
            | Some(Event::DeviceEvent { .. })
            | Some(Event::UserEvent { .. })
            | Some(Event::MainEventsCleared) => {
                shared_state.next_event = None;
                Poll::Pending
            }

            Some(Event::NewEvents { .. }) | Some(Event::LoopDestroyed) => unreachable!(),
            Some(Event::Suspended) | Some(Event::Resumed) => unimplemented!(),
            None => Poll::Pending,
        }
    }
}