use crate::*;
use ::type_sets::{Contains, Members, SubsetOf};
use futures::{future::BoxFuture, Future};
use std::{
any::{type_name, Any, TypeId},
fmt::Debug,
marker::PhantomData,
};
#[macro_export]
macro_rules! DynSender {
($($tt:tt)*) => {
$crate::DynSender::<$crate::Set![$($tt)*]>
};
}
pub struct DynSender<A, W = ()> {
sender: BoxedSender<W>,
t: PhantomData<fn() -> A>,
}
impl<A, W> DynSender<A, W> {
pub fn new<S>(sender: S) -> Self
where
S: SendsProtocol + DynSends<With = W>,
A: SubsetOf<S::Protocol>,
{
Self::new_unchecked(sender)
}
pub fn new_unchecked<S>(sender: S) -> Self
where
S: DynSends<With = W>,
{
Self::from_boxed_unchecked(Box::new(sender))
}
pub fn transform<A2>(self) -> DynSender<A2, W>
where
A2: SubsetOf<A>,
{
DynSender::from_boxed_unchecked(self.sender)
}
pub fn try_transform<A2>(self) -> Result<DynSender<A2, W>, Self>
where
A2: Members,
W: 'static,
A: 'static,
{
if A2::members().iter().all(|t2| self.members().contains(t2)) {
Ok(DynSender::from_boxed_unchecked(self.sender))
} else {
Err(self)
}
}
pub fn transform_unchecked<A2>(self) -> DynSender<A2, W> {
DynSender::from_boxed_unchecked(self.sender)
}
pub fn from_boxed_unchecked(sender: BoxedSender<W>) -> Self {
Self {
sender,
t: PhantomData,
}
}
pub fn into_boxed_sender(self) -> BoxedSender<W> {
self.sender
}
pub fn downcast_ref<S>(&self) -> Option<&S>
where
S: IsSender<With = W> + 'static,
W: 'static,
{
self.sender.as_any().downcast_ref::<S>()
}
}
impl<A, W> IsSender for DynSender<A, W> {
type With = W;
fn is_closed(&self) -> bool {
self.sender.is_closed()
}
fn capacity(&self) -> Option<usize> {
self.sender.capacity()
}
fn len(&self) -> usize {
self.sender.len()
}
fn receiver_count(&self) -> usize {
self.sender.receiver_count()
}
fn sender_count(&self) -> usize {
self.sender.sender_count()
}
}
impl<A, W> DynSends for DynSender<A, W>
where
A: 'static,
W: 'static,
{
fn dyn_send_boxed_msg_with(
&self,
msg: BoxedMsg<Self::With>,
) -> BoxFuture<Result<(), DynSendError<BoxedMsg<Self::With>>>> {
self.sender.dyn_send_boxed_msg_with(msg)
}
fn dyn_send_boxed_msg_blocking_with(
&self,
msg: BoxedMsg<Self::With>,
) -> Result<(), DynSendError<BoxedMsg<Self::With>>> {
self.sender.dyn_send_boxed_msg_blocking_with(msg)
}
fn dyn_try_send_boxed_msg_with(
&self,
msg: BoxedMsg<Self::With>,
) -> Result<(), DynTrySendError<BoxedMsg<Self::With>>> {
self.sender.dyn_try_send_boxed_msg_with(msg)
}
fn members(&self) -> &'static [TypeId] {
self.sender.members()
}
fn clone_boxed(&self) -> BoxedSender<Self::With> {
self.sender.clone_boxed()
}
fn as_any(&self) -> &dyn Any {
self.sender.as_any()
}
}
impl<A, W, M> Sends<M> for DynSender<A, W>
where
A: Contains<M>,
M: Send + 'static,
W: Send + 'static,
{
fn send_msg_with(
this: &Self,
msg: M,
with: Self::With,
) -> impl Future<Output = Result<(), SendError<(M, Self::With)>>> + Send {
let fut = this.sender.dyn_send_msg_with(msg, with);
async {
match fut.await {
Ok(()) => Ok(()),
Err(e) => Err(match e {
DynSendError::NotAccepted(_e) => {
panic!("Message not accepted: {}", type_name::<(M, Self::With)>())
}
DynSendError::Closed((msg, with)) => SendError((msg, with)),
}),
}
}
}
fn try_send_msg_with(
this: &Self,
msg: M,
with: Self::With,
) -> Result<(), TrySendError<(M, Self::With)>> {
match this.sender.dyn_try_send_msg_with(msg, with) {
Ok(()) => Ok(()),
Err(e) => Err(match e {
DynTrySendError::NotAccepted(_e) => {
panic!("Message not accepted: {}", type_name::<(M, Self::With)>())
}
DynTrySendError::Closed((msg, with)) => TrySendError::Closed((msg, with)),
DynTrySendError::Full((msg, with)) => TrySendError::Full((msg, with)),
}),
}
}
}
impl<A, W: Debug> Debug for DynSender<A, W> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DynSender")
.field("sender", &"...")
.field("t", &type_name::<A>())
.finish()
}
}
impl<A, W: 'static> Clone for DynSender<A, W> {
fn clone(&self) -> Self {
Self {
sender: self.sender.clone(),
t: PhantomData,
}
}
}