use std::{
any,
borrow::Cow,
collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
fmt,
marker::PhantomData,
num::{
NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
},
path::{Path, PathBuf},
sync::{
Arc, Mutex, Once, RwLock,
atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize},
},
thread::Thread,
};
#[cfg(target_has_atomic = "8")]
use std::sync::atomic::{AtomicI8, AtomicU8};
#[cfg(target_has_atomic = "16")]
use std::sync::atomic::{AtomicI16, AtomicU16};
#[cfg(target_has_atomic = "32")]
use std::sync::atomic::{AtomicI32, AtomicU32};
#[cfg(target_has_atomic = "64")]
use std::sync::atomic::{AtomicI64, AtomicU64};
use downcast_rs::{DowncastSend, impl_downcast};
use futures::Future;
use tokio::sync::oneshot;
use crate::{
Actor,
actor::{
ActorId, ActorRef, PreparedActor, Recipient, ReplyRecipient, WeakActorRef, WeakRecipient,
WeakReplyRecipient,
},
error::{ActorStopReason, BoxSendError, Infallible, PanicError, SendError},
mailbox::{MailboxReceiver, MailboxSender},
message::{BoxReply, Context},
};
pub type BoxReplySender = oneshot::Sender<Result<BoxReply, BoxSendError>>;
pub trait Reply: Send + 'static {
type Ok: Send + 'static;
type Error: ReplyError;
type Value: Reply;
fn to_result(self) -> Result<Self::Ok, Self::Error>;
fn into_any_err(self) -> Option<Box<dyn ReplyError>>;
fn into_value(self) -> Self::Value;
fn downcast_ok(ok: Box<dyn any::Any>) -> Self::Ok {
*ok.downcast().unwrap()
}
fn downcast_err<M: 'static>(err: BoxSendError) -> SendError<M, Self::Error> {
err.downcast()
}
}
#[must_use = "the receiver expects a reply to be sent"]
pub struct ReplySender<R: ?Sized> {
tx: BoxReplySender,
phantom: PhantomData<R>,
}
impl<R> ReplySender<R> {
pub(crate) fn new(tx: BoxReplySender) -> Self {
ReplySender {
tx,
phantom: PhantomData,
}
}
pub fn boxed(self) -> BoxReplySender {
self.tx
}
pub fn send(self, reply: R)
where
R: Reply,
{
let _ = self.tx.send(
reply
.to_result()
.map(|value| Box::new(value) as BoxReply)
.map_err(|err| BoxSendError::HandlerError(Box::new(err))),
);
}
pub(crate) fn cast<R2>(self) -> ReplySender<R2> {
ReplySender {
tx: self.tx,
phantom: PhantomData,
}
}
}
impl<R: ?Sized> fmt::Debug for ReplySender<R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ReplySender")
.field("tx", &self.tx)
.field("phantom", &self.phantom)
.finish()
}
}
pub trait ReplyError: DowncastSend + fmt::Debug + 'static {}
impl<T> ReplyError for T where T: fmt::Debug + Send + 'static {}
impl_downcast!(ReplyError);
#[must_use = "the deligated reply should be returned by the handler"]
#[derive(Clone, Copy, Debug)]
pub struct DelegatedReply<R> {
phantom: PhantomData<fn() -> R>,
}
impl<R> DelegatedReply<R> {
pub(crate) fn new() -> Self {
DelegatedReply {
phantom: PhantomData,
}
}
}
impl<R> Reply for DelegatedReply<R>
where
R: Reply,
{
type Ok = R::Ok;
type Error = R::Error;
type Value = R::Value;
fn to_result(self) -> Result<Self::Ok, Self::Error> {
unimplemented!("a DeligatedReply cannot be converted to a result and is only a marker type")
}
fn into_any_err(self) -> Option<Box<dyn ReplyError>> {
None
}
fn into_value(self) -> Self::Value {
unimplemented!("a DeligatedReply cannot be converted to a value and is only a marker type")
}
}
include!("reply/forwarded.rs");
include!("reply/standard_impls.rs");
include!("reply/tests.rs");