use std::marker::PhantomData;
use serde::{de::DeserializeOwned, Serialize};
use crate::Channel;
#[macro_export]
macro_rules! pipe {
(send $t: ty) => {
$crate::type_iter::TypeIter<$crate::type_iter::Tx<$t>>
};
(receive $t: ty) => {
$crate::type_iter::TypeIter<$crate::type_iter::Rx<$t>>
};
(send $t: ty) => {
$crate::type_iter::TypeIter<$crate::type_iter::Tx<$t>>
};
(receive $t: ty) => {
$crate::type_iter::TypeIter<$crate::type_iter::Rx<$t>>
};
(send $t: ty, $($lit: ident $s: ty),*) => {
$crate::type_iter::TypeIter<$crate::type_iter::Tx<$t>, $crate::pipe!($($lit $s),*)>
};
(receive $t: ty, $($lit: ident $s: ty),*) => {
$crate::type_iter::TypeIter<$crate::type_iter::Rx<$t>, $crate::pipe!($($lit $s),*)>
};
(send $t: ty, $($lit: ident $s: ty),*) => {
$crate::type_iter::TypeIter<$crate::type_iter::Tx<$t>, $crate::pipe!($($lit $s),*)>
};
(receive $t: ty, $($lit: ident $s: ty),*) => {
$crate::type_iter::TypeIter<$crate::type_iter::Rx<$t>, $crate::pipe!($($lit $s),*)>
};
}
#[macro_export]
macro_rules! send {
($i: ident, $e: expr) => {
#[allow(unused_variables)] let $i = $i.send($e).await?;
};
}
#[macro_export]
macro_rules! receive {
($i: ident, $e: ident) => {
let ($i, $e) = $e.receive().await?;
#[allow(unused_variables)] let $e = $e;
};
}
#[macro_export]
macro_rules! pipeline {
() => {};
(
$v: vis pipeline $i: ident {
$($lit: ident $s: ty),*
$(,)?
}
) => {
$v struct $i;
impl $crate::type_iter::Pipeline for $i {
type Pipe = $crate::pipe!($($lit $s),*);
}
};
}
pub trait TypeIterT {
type Next;
type Type;
}
impl TypeIterT for () {
type Next = ();
type Type = ();
}
#[derive(Default)]
pub struct TypeIter<T, L = ()>(PhantomData<T>, PhantomData<L>);
impl<T, L: TypeIterT> TypeIterT for TypeIter<T, L> {
type Next = L;
type Type = T;
}
pub trait Transmit {
type Type;
}
pub trait Receive {
type Type;
}
impl<T> Transmit for Tx<T> {
type Type = T;
}
impl<T> Receive for Rx<T> {
type Type = T;
}
pub struct Tx<T>(T);
pub struct Rx<T>(T);
pub trait Pipeline {
type Pipe: TypeIterT;
}
impl Pipeline for () {
type Pipe = ();
}
pub trait Str {}
impl Str for Tx<String> {}
impl Str for Tx<&str> {}
pub trait Slice<T> {}
impl<T> Slice<T> for Tx<&[T]> {}
impl<T> Slice<T> for Tx<Vec<T>> {}
pub struct MainChannel<T: TypeIterT>(pub(crate) PhantomData<T>, pub(crate) Channel);
impl<T: TypeIterT> MainChannel<T> {
pub fn new<P: Pipeline>(chan: Channel) -> MainChannel<P::Pipe> {
MainChannel(PhantomData, chan)
}
pub async fn send(
mut self,
obj: <T::Type as Transmit>::Type,
) -> crate::Result<MainChannel<T::Next>>
where
T::Type: Transmit,
<T as TypeIterT>::Next: TypeIterT,
<<T as TypeIterT>::Type as Transmit>::Type: Serialize + Send,
{
self.1.send(obj).await?;
Ok(MainChannel(PhantomData, self.1))
}
pub async fn receive(
mut self,
) -> crate::Result<(<T::Type as Receive>::Type, MainChannel<T::Next>)>
where
T::Type: Receive,
<T as TypeIterT>::Next: TypeIterT,
<T::Type as Receive>::Type: DeserializeOwned,
{
let res = self.1.receive::<<T::Type as Receive>::Type>().await?;
let chan = MainChannel(PhantomData, self.1);
Ok((res, chan))
}
pub fn coerce(self) -> Channel {
self.1
}
pub async fn send_str(mut self, obj: &str) -> crate::Result<MainChannel<T::Next>>
where
T::Type: Transmit + Str,
<T as TypeIterT>::Next: TypeIterT,
<<T as TypeIterT>::Type as Transmit>::Type: Serialize + Send,
{
self.1.send(obj).await?;
Ok(MainChannel(PhantomData, self.1))
}
pub async fn send_slice(mut self, obj: &[T::Type]) -> crate::Result<MainChannel<T::Next>>
where
T::Type: Transmit + Slice<T::Type> + Serialize,
<T as TypeIterT>::Next: TypeIterT,
<<T as TypeIterT>::Type as Transmit>::Type: Serialize + Send,
{
self.1.send(obj).await?;
Ok(MainChannel(PhantomData, self.1))
}
}
pub struct PeerChannel<T: TypeIterT>(pub(crate) PhantomData<T>, pub(crate) Channel);
impl<T: TypeIterT> PeerChannel<T> {
pub fn new<P: Pipeline>(chan: Channel) -> PeerChannel<P::Pipe>
where
<P as Pipeline>::Pipe: TypeIterT,
{
PeerChannel(PhantomData, chan)
}
pub async fn send(
mut self,
obj: <T::Type as Receive>::Type,
) -> crate::Result<PeerChannel<T::Next>>
where
T::Type: Receive,
<T as TypeIterT>::Next: TypeIterT,
<<T as TypeIterT>::Type as Receive>::Type: Serialize + Send,
{
self.1.send(obj).await?;
Ok(PeerChannel(PhantomData, self.1))
}
pub async fn receive(
mut self,
) -> crate::Result<(<T::Type as Transmit>::Type, PeerChannel<T::Next>)>
where
T::Type: Transmit,
<T as TypeIterT>::Next: TypeIterT,
<T::Type as Transmit>::Type: DeserializeOwned + 'static,
{
let res = self.1.receive::<<T::Type as Transmit>::Type>().await?;
let chan = PeerChannel(PhantomData, self.1);
Ok((res, chan))
}
pub fn channel(self) -> Channel {
self.1
}
pub async fn send_str(mut self, obj: &str) -> crate::Result<PeerChannel<T::Next>>
where
T::Type: Transmit + Str,
<T as TypeIterT>::Next: TypeIterT,
<<T as TypeIterT>::Type as Transmit>::Type: Serialize + Send,
{
self.1.send(obj).await?;
Ok(PeerChannel(PhantomData, self.1))
}
pub async fn send_slice(mut self, obj: &[T::Type]) -> crate::Result<PeerChannel<T::Next>>
where
T::Type: Transmit + Slice<T::Type> + Serialize,
<T as TypeIterT>::Next: TypeIterT,
<<T as TypeIterT>::Type as Transmit>::Type: Serialize + Send,
{
self.1.send(obj).await?;
Ok(PeerChannel(PhantomData, self.1))
}
}