mod reactor;
use crate::coord::Vec2;
use std::sync::Mutex;
use tokio::sync::Notify;
pub(crate) use reactor::Reactor;
pub type Epoch = u128;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Key {
Char(char),
Up,
Down,
Left,
Right,
Esc,
Enter,
Backspace,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct KeyEvent {
pub main_key: Key,
pub ctrl: bool,
pub alt: bool,
pub shift: bool,
}
impl KeyEvent {
fn dummy() -> Self {
Self { main_key: Key::Esc, ctrl: false, alt: false, shift: false }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ResizeEvent {
pub size: Option<Vec2>,
}
impl ResizeEvent {
fn dummy() -> Self {
Self { size: None }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Event {
Resize(ResizeEvent),
Key(KeyEvent),
}
impl From<ResizeEvent> for Event {
fn from(event: ResizeEvent) -> Self {
Event::Resize(event)
}
}
impl From<KeyEvent> for Event {
fn from(event: KeyEvent) -> Self {
Event::Key(event)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Snapshot<E> {
event: E,
epoch: Epoch,
}
#[derive(Debug)]
struct ChannelData {
key: Snapshot<KeyEvent>,
resize: Snapshot<ResizeEvent>,
}
impl Default for ChannelData {
fn default() -> Self {
Self {
key: Snapshot { event: KeyEvent::dummy(), epoch: 0 },
resize: Snapshot { event: ResizeEvent::dummy(), epoch: 0 },
}
}
}
impl ChannelData {
fn epoch(&self) -> Epoch {
self.key.epoch.max(self.resize.epoch)
}
fn read(&self, epoch: Epoch) -> Option<(Epoch, Event)> {
if self.resize.epoch > epoch {
Some((self.resize.epoch, self.resize.event.into()))
} else if self.key.epoch > epoch {
Some((self.key.epoch, self.key.event.into()))
} else {
None
}
}
fn write(&mut self, event: Event) {
let epoch = self.epoch();
match event {
Event::Key(event) => {
self.key = Snapshot { epoch: epoch + 1, event }
},
Event::Resize(event) => {
self.resize = Snapshot { epoch: epoch + 1, event }
},
}
}
}
#[derive(Debug)]
pub(crate) struct Channel {
data: Mutex<ChannelData>,
notifier: Notify,
}
impl Default for Channel {
fn default() -> Self {
Channel {
data: Mutex::new(ChannelData::default()),
notifier: Notify::new(),
}
}
}
impl Channel {
pub fn notify(&self) {
self.notifier.notify_waiters()
}
pub async fn subscribe(&self) {
self.notifier.notified().await
}
pub fn epoch(&self) -> Epoch {
self.data.lock().unwrap().epoch()
}
pub fn read(&self, epoch: Epoch) -> Option<(Epoch, Event)> {
self.data.lock().unwrap().read(epoch)
}
pub fn write(&self, event: Event) {
self.data.lock().unwrap().write(event)
}
}