use crate::all::*;
use futures::Future;
use std::{
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
pub trait HandlerState<H: Handler>: ActorRef<ActorType = Self::InboxType> + Unpin + Send {
type Protocol: Protocol + HandledBy<H>;
type InboxType: InboxType;
fn from_inbox(inbox: Self::InboxType) -> Self;
fn poll_next_item(
self: Pin<&mut Self>,
cx: &mut Context,
) -> Poll<HandlerItem<Self::Protocol, H>>;
}
pub enum HandlerItem<P, S: Handler> {
Protocol(P),
Action(Action<S>),
Event(Event),
HandlerResult(Result<Flow<S>, S::Exception>),
}
impl<P, H: Handler> HandlerItem<P, H> {
pub fn is_dead(&self) -> bool {
if let Self::Event(Event::Dead) = self {
true
} else {
false
}
}
}
impl<P, H> HandlerItem<P, H>
where
H: Handler,
P: HandledBy<H>,
{
pub async fn handle_with(self, handler: &mut H, state: &mut H::State) -> HandlerResult<H> {
match self {
HandlerItem::Event(event) => handler.handle_event(state, event).await,
HandlerItem::Action(action) => action.handle_with(handler, state).await,
HandlerItem::Protocol(protocol) => protocol.handle_with(handler, state).await,
HandlerItem::HandlerResult(result) => result,
}
}
}
pub trait HandlerStateExt<H: Handler>: HandlerState<H> {
fn next_handler_item(&mut self) -> NextHandlerItem<'_, Self, H>
where
Self: Unpin,
{
NextHandlerItem(self, PhantomData)
}
}
impl<T: HandlerState<H>, H: Handler> HandlerStateExt<H> for T {}
pub struct NextHandlerItem<'a, S: HandlerState<H>, H: Handler>(&'a mut S, PhantomData<H>);
impl<'a, S: HandlerState<H>, H: Handler> Unpin for NextHandlerItem<'a, S, H> {}
impl<'a, S: HandlerState<H> + Unpin, H: Handler> Future for NextHandlerItem<'a, S, H> {
type Output = HandlerItem<S::Protocol, H>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut *self.0).poll_next_item(cx)
}
}