pub mod channel;
use std::ops::ControlFlow;
use super::{
queue::{Queue, QueueEditGuard},
ClientState,
};
use crate::ircmsg::ServerMsg;
use channel::*;
pub trait Handler: 'static + Send {
type Value: 'static;
fn handle(
&mut self,
msg: &ServerMsg<'_>,
state: &mut ClientState,
queue: QueueEditGuard<'_>,
channel: SenderRef<'_, Self::Value>,
) -> ControlFlow<()>;
fn wants_owning(&self) -> bool {
false
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
pub struct NoHandler;
impl std::fmt::Display for NoHandler {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "handler intentionally not created")
}
}
impl std::error::Error for NoHandler {}
pub trait MakeHandler<T> {
type Value: 'static;
type Error;
type Receiver<Spec: ChannelSpec>;
fn make_handler(
self,
state: &ClientState,
queue: QueueEditGuard<'_>,
value: T,
) -> Result<Box<dyn Handler<Value = Self::Value>>, Self::Error>;
fn make_channel<Spec: ChannelSpec>(
spec: &Spec,
) -> (Box<dyn Sender<Value = Self::Value> + Send>, Self::Receiver<Spec>);
}
pub trait SelfMadeHandler: Handler {
type Receiver<Spec: ChannelSpec>;
fn queue_msgs(&self, state: &ClientState, queue: QueueEditGuard<'_>);
fn make_channel<Spec: ChannelSpec>(
spec: &Spec,
) -> (Box<dyn Sender<Value = Self::Value> + Send>, Self::Receiver<Spec>);
}
impl<T: SelfMadeHandler> MakeHandler<T> for () {
type Value = T::Value;
type Error = std::convert::Infallible;
type Receiver<Spec: ChannelSpec> = T::Receiver<Spec>;
fn make_handler(
self,
state: &ClientState,
queue: QueueEditGuard<'_>,
handler: T,
) -> Result<Box<dyn Handler<Value = T::Value>>, Self::Error> {
handler.queue_msgs(state, queue);
Ok(Box::new(handler))
}
fn make_channel<Spec: ChannelSpec>(
spec: &Spec,
) -> (Box<dyn Sender<Value = Self::Value> + Send>, Self::Receiver<Spec>) {
T::make_channel(spec)
}
}
type BoxHandler =
Box<dyn FnMut(&ServerMsg<'_>, &mut ClientState, QueueEditGuard<'_>) -> HandlerStatus + Send>;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum HandlerStatus {
Keep { yielded: bool, wants_owning: bool },
Done { yielded: bool },
}
fn box_handler<T: 'static>(
mut handler: Box<dyn Handler<Value = T>>,
mut sender: Box<dyn Sender<Value = T> + Send>,
) -> BoxHandler {
Box::new(move |msg, state, queue| {
let mut yielded = false;
let sr = SenderRef { sender: &mut *sender, flag: &mut yielded };
if handler.handle(msg, state, queue, sr).is_break() {
HandlerStatus::Done { yielded }
} else {
HandlerStatus::Keep { yielded, wants_owning: handler.wants_owning() }
}
})
}
pub(crate) struct Handlers {
handlers: Vec<(BoxHandler, usize)>,
yielded: Vec<usize>,
finished: Vec<usize>,
wants_owning: bool,
}
impl Default for Handlers {
fn default() -> Self {
Handlers {
handlers: Vec::with_capacity(2),
yielded: Vec::new(),
finished: Vec::with_capacity(1),
wants_owning: false,
}
}
}
impl Handlers {
pub fn add<T: 'static>(
&mut self,
handler: Box<dyn Handler<Value = T>>,
sender: Box<dyn Sender<Value = T> + Send>,
) -> usize {
self.wants_owning |= handler.wants_owning();
let id = self.finished.pop().unwrap_or(self.handlers.len());
let boxed = box_handler(handler, sender);
self.handlers.push((boxed, id));
id
}
pub fn is_empty(&self) -> bool {
self.handlers.is_empty()
}
#[allow(unused)]
pub fn wants_owning(&self) -> bool {
self.wants_owning
}
#[allow(unused)]
pub fn cancel_one(&mut self, id: usize) {
if let Some(idx) = self.handlers.iter().position(|(_, id2)| id == *id2) {
self.handlers.swap_remove(idx);
self.finished.push(id);
self.wants_owning &= !self.handlers.is_empty();
} else {
panic!("attemped to cancel handler with invalid id")
}
}
pub fn cancel(&mut self) {
self.handlers.clear();
self.finished.clear();
self.yielded.clear();
self.wants_owning = false;
}
pub fn has_results(&self, finished_at: usize) -> bool {
!self.yielded.is_empty() || self.finished.len() > finished_at
}
pub fn last_run_results(&self, finished_at: usize) -> (&[usize], &[usize]) {
let (_, finished) = self.finished.split_at(finished_at);
(self.yielded.as_slice(), finished)
}
pub fn handle(
&mut self,
msg: &ServerMsg<'_>,
state: &mut ClientState,
queue: &mut Queue,
) -> usize {
self.wants_owning = false;
self.yielded.clear();
let finished_at = self.finished.len();
let mut i = 0usize;
while let Some((handler, id)) = self.handlers.get_mut(i) {
match (handler)(msg, state, queue.edit()) {
HandlerStatus::Keep { yielded, wants_owning } => {
if yielded {
self.yielded.push(*id);
}
self.wants_owning |= wants_owning;
i += 1;
}
HandlerStatus::Done { yielded } => {
if yielded {
self.yielded.push(*id);
}
self.finished.push(*id);
let _ = self.handlers.swap_remove(i);
}
}
}
finished_at
}
}
#[inline]
pub fn cf_discard<A, B>(cf: ControlFlow<A, B>) -> ControlFlow<()> {
match cf {
ControlFlow::Continue(_) => ControlFlow::Continue(()),
ControlFlow::Break(_) => ControlFlow::Break(()),
}
}