use crate::unary::{LessThan, Unary, S, Z};
mod call;
mod choose;
mod r#continue;
mod done;
mod r#loop;
mod offer;
mod recv;
mod send;
mod split;
pub use call::*;
pub use choose::*;
pub use done::*;
pub use offer::*;
pub use r#continue::*;
pub use r#loop::*;
pub use recv::*;
pub use send::*;
pub use split::*;
pub trait HasDual: sealed::IsSession + Sized + 'static {
type DualSession: HasDual<DualSession = Self>;
}
pub trait Actionable: sealed::IsSession {
type NextAction: Actionable<NextAction = Self::NextAction>;
}
pub trait Scoped<N: Unary = Z>: sealed::IsSession {}
pub trait EachScoped<N: Unary = Z>: sealed::EachSession {}
impl<N: Unary> EachScoped<N> for () {}
impl<N: Unary, P: Scoped<N>, Ps: EachScoped<N>> EachScoped<N> for (P, Ps) {}
pub trait EachHasDual: sealed::EachSession + Sized + 'static
where
Self::Duals: EachHasDual<Duals = Self>,
{
type Duals;
}
impl EachHasDual for () {
type Duals = ();
}
impl<P, Ps> EachHasDual for (P, Ps)
where
P: HasDual,
Ps: EachHasDual,
{
type Duals = (P::DualSession, Ps::Duals);
}
pub trait Subst<P, N: Unary = Z>: sealed::IsSession {
type Substituted: 'static;
}
pub trait Then<P, N: Unary = Z>: sealed::IsSession {
type Combined: 'static;
}
pub trait Lift<N: Unary, Level: Unary = Z>: sealed::IsSession {
type Lifted: 'static;
}
pub trait EachSubst<P, N: Unary = Z>: sealed::EachSession {
type Substituted: 'static;
}
impl<N: Unary, Q> EachSubst<Q, N> for () {
type Substituted = ();
}
impl<N: Unary, Q, P, Ps> EachSubst<Q, N> for (P, Ps)
where
P: Subst<Q, N>,
Ps: EachSubst<Q, N>,
{
type Substituted = (P::Substituted, Ps::Substituted);
}
pub trait EachThen<P, N: Unary = Z>: sealed::EachSession {
type Combined: 'static;
}
impl<N: Unary, Q> EachThen<Q, N> for () {
type Combined = ();
}
impl<N: Unary, Q, P, Ps> EachThen<Q, N> for (P, Ps)
where
P: Then<Q, N>,
Ps: EachThen<Q, N>,
{
type Combined = (P::Combined, Ps::Combined);
}
pub trait EachLift<N: Unary, Level: Unary = Z>: sealed::EachSession {
type Lifted: 'static;
}
impl<N: Unary, Level: Unary> EachLift<N, Level> for () {
type Lifted = ();
}
impl<N: Unary, Level: Unary, P, Ps> EachLift<N, Level> for (P, Ps)
where
P: Lift<N, Level>,
Ps: EachLift<N, Level>,
{
type Lifted = (P::Lifted, Ps::Lifted);
}
pub trait Select<N: Unary>: sealed::Select<N> {
type Selected;
type Remainder;
}
impl<T, Rest> Select<Z> for (T, Rest) {
type Selected = T;
type Remainder = Rest;
}
impl<T, P, Rest, N: Unary> Select<S<N>> for (T, (P, Rest))
where
(P, Rest): Select<N>,
{
type Selected = <(P, Rest) as Select<N>>::Selected;
type Remainder = (T, <(P, Rest) as Select<N>>::Remainder);
}
mod sealed {
use std::any::Any;
use super::*;
pub trait IsSession: Any {}
pub trait EachSession {}
impl EachSession for () {}
impl<T: IsSession, Ts: EachSession> EachSession for (T, Ts) {}
pub trait Select<N: Unary> {}
impl<T, S> Select<Z> for (T, S) {}
impl<T, P, Rest, N: Unary> Select<S<N>> for (T, (P, Rest)) where (P, Rest): Select<N> {}
}
#[cfg(test)]
#[macro_export]
macro_rules! assert_all_closed_sessions {
() => {};
($session:ty) => { assert_all_closed_sessions!($session,) };
($session:ty, $($rest:tt)*) => {
const _: fn() = || {
fn assert_impl_all<T>()
where
T: $crate::Session,
<T as Session>::Dual: $crate::Session,
{
}
assert_impl_all::<$session>();
};
assert_all_closed_sessions!($($rest)*);
};
}
#[cfg(test)]
mod tests {
#[allow(unused_imports)]
use super::*;
#[test]
fn complex_session_zero_size() {
type P = Loop<
Loop<
Choose<(
Send<usize, Continue<0>>,
Recv<String, Continue<0>>,
Offer<(
Send<bool, Continue<0>>,
Continue<1>,
Split<Send<isize, Continue<0>>, Recv<isize, Continue<0>>, Done>,
)>,
)>,
>,
>;
assert_eq!(std::mem::size_of::<P>(), 0);
}
include!(concat!(env!("OUT_DIR"), "/valid_sessions.rs"));
}