use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};
use heph_inbox::{self as inbox, Receiver, RecvValue};
use crate::actor_ref::ActorRef;
#[derive(Debug)]
pub struct Context<M, RT> {
pub(crate) inbox: Receiver<M>,
rt: RT,
}
impl<M, RT> Context<M, RT> {
#[doc(hidden)] pub const fn new(inbox: Receiver<M>, rt: RT) -> Context<M, RT> {
Context { inbox, rt }
}
pub fn try_receive_next(&mut self) -> Result<M, RecvError> {
self.inbox.try_recv().map_err(RecvError::from)
}
pub fn receive_next<'ctx>(&'ctx mut self) -> ReceiveMessage<'ctx, M> {
ReceiveMessage {
recv: self.inbox.recv(),
}
}
pub fn actor_ref(&self) -> ActorRef<M> {
ActorRef::local(self.inbox.new_sender())
}
pub fn runtime(&mut self) -> &mut RT {
&mut self.rt
}
pub const fn runtime_ref(&self) -> &RT {
&self.rt
}
#[doc(hidden)] pub fn register_inbox_waker(&mut self, waker: &task::Waker) {
let _ = self.inbox.register_waker(waker);
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RecvError {
Empty,
Disconnected,
}
impl RecvError {
pub(crate) const fn from(err: inbox::RecvError) -> RecvError {
match err {
inbox::RecvError::Empty => RecvError::Empty,
inbox::RecvError::Disconnected => RecvError::Disconnected,
}
}
}
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ReceiveMessage<'ctx, M> {
recv: RecvValue<'ctx, M>,
}
impl<'ctx, M> Future for ReceiveMessage<'ctx, M> {
type Output = Result<M, NoMessages>;
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> Poll<Self::Output> {
Pin::new(&mut self.recv)
.poll(ctx)
.map(|r| r.ok_or(NoMessages))
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct NoMessages;
impl fmt::Display for NoMessages {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("no messages in inbox")
}
}