generic_session_types/chan/
mod.rs1use crate::*;
2use std::{future::Future, marker::PhantomData};
3
4pub trait RawChan {
5 type R;
6 type SendFuture<'a>: Future<Output = Result<(), Error>> + 'a
7 where
8 Self: 'a;
9 fn send(&mut self, r: Self::R) -> Self::SendFuture<'_>;
10
11 type RecvFuture<'a>: Future<Output = Result<Self::R, Error>>
12 where
13 Self: 'a;
14 fn recv(&mut self) -> Self::RecvFuture<'_>;
15
16 type CloseFuture: Future<Output = Result<(), Error>> + 'static;
17 fn close(self) -> Self::CloseFuture;
18}
19
20#[repr(transparent)]
21#[must_use]
22pub struct Chan<P: HasDual, E, C: RawChan>(C, PhantomData<(P, E)>);
23
24impl<P: HasDual, E, C: RawChan> Chan<P, E, C> {
25 pub fn from_raw(c: C) -> Self {
26 Self(c, PhantomData)
27 }
28 pub fn into_raw(self) -> C {
29 self.0
30 }
31}
32
33impl<P: HasDual, E, T, C: RawChan> Chan<Send<T, P>, E, C>
34where
35 C::R: Repr<T>,
36{
37 pub async fn send(self, t: T) -> Result<Chan<P, E, C>, Error> {
38 let mut c = self.0;
39 let r = <C::R as Repr<T>>::from(t);
40 c.send(r).await?;
41 let chan = Chan(c, PhantomData);
42 Ok(chan)
43 }
44}
45
46impl<P: HasDual, E, T, C: RawChan> Chan<Recv<T, P>, E, C>
47where
48 C::R: Repr<T>,
49{
50 pub async fn recv(self) -> Result<(T, Chan<P, E, C>), Error> {
51 let mut c = self.0;
52 let r = c.recv().await.map_err(|_| Error::RecvErr)?;
53 let t: T = repr::Repr::try_into(r).map_err(|_| Error::ConvertErr)?;
54 let chan = Chan(c, PhantomData);
55 Ok((t, chan))
56 }
57}
58
59impl<P: HasDual, Q: HasDual, E, C: RawChan> Chan<Choose<P, Q>, E, C>
60where
61 C::R: Repr<bool>,
62{
63 pub async fn left(self) -> Result<Chan<P, E, C>, Error> {
64 let mut c = self.0;
65 c.send(<C::R as Repr<bool>>::from(false)).await?;
66 Ok(Chan(c, PhantomData))
67 }
68 pub async fn right(self) -> Result<Chan<Q, E, C>, Error> {
69 let mut c = self.0;
70 c.send(<C::R as Repr<bool>>::from(true)).await?;
71 Ok(Chan(c, PhantomData))
72 }
73}
74
75pub enum Branch<L, R> {
76 Left(L),
77 Right(R),
78}
79
80impl<P: HasDual, Q: HasDual, E, C: RawChan> Chan<Offer<P, Q>, E, C>
81where
82 C::R: Repr<bool>,
83{
84 pub async fn offer(self) -> Result<Branch<Chan<P, E, C>, Chan<Q, E, C>>, Error> {
85 let mut c = self.0;
86 let r = c.recv().await.map_err(|_| Error::RecvErr)?;
87 let b = repr::Repr::try_into(r).map_err(|_| Error::ConvertErr)?;
88 match b {
89 false => Ok(Branch::Left(Chan(c, PhantomData))),
90 true => Ok(Branch::Right(Chan(c, PhantomData))),
91 }
92 }
93}
94
95impl<P: HasDual, E, C: RawChan> Chan<Rec<P>, E, C> {
96 pub fn rec(self) -> Chan<P, (P, E), C> {
97 Chan::from_raw(self.into_raw())
98 }
99}
100
101impl<P: HasDual, E, C: RawChan> Chan<Var<Z>, (P, E), C> {
102 pub fn zero(self) -> Chan<P, (P, E), C> {
103 Chan::from_raw(self.into_raw())
104 }
105}
106
107impl<P: HasDual, E, N, C: RawChan> Chan<Var<S<N>>, (P, E), C>
108where
109 Var<N>: HasDual,
110{
111 pub fn succ(self) -> Chan<Var<N>, E, C> {
112 Chan::from_raw(self.into_raw())
113 }
114}
115
116impl<C: RawChan, E> Chan<Close, E, C> {
117 pub async fn close(self) -> Result<(), Error> {
118 self.0.close().await
119 }
120}
121
122#[macro_export]
123macro_rules! send {
124 ( $c:ident, $msg:expr ) => {
125 let $c = $c.send($msg).await?;
126 };
127}
128
129#[macro_export]
130macro_rules! recv {
131 ( $c:ident, $msg:ident ) => {
132 let ($msg, $c) = $c.recv().await?;
133 };
134}
135
136#[macro_export]
137macro_rules! close {
138 ( $c:ident ) => {
139 $c.close().await?;
140 };
141}
142#[macro_export]
143macro_rules! choose_offer {
144 ( $choose:ident $offer:ident {
145 $($p:ident ( $t:ty ) $o:ident),+
146 } with $offerExt:ident) => {
147 struct $choose {
148 }
149
150 enum $offer {
151 }
152
153 impl HasDual for $choose { type Dual = $offer; }
154
155 impl HasDual for $offer { type Dual = $choose; }
156
157 choose_offer!($choose; 0; $($p($t)),*); choose_offer!($offer $offerExt; $($o < $t as HasDual>::Dual),*);
160 };
161
162 ($choose:ident; $e:expr ; ) => {};
164 ($choose:ident; $e:expr ; $p:ident ($t:ty) $(, $ps:ident ($ts:ty) )* ) => {
165 async fn $p<E, C: RawChan>(chan: Chan< $choose, E, C>) -> Result< Chan< $t, E, C>, Error>
166 where
167 <C as $crate::RawChan>::R: $crate::Repr<u8>,
168 {
169 let mut c = chan.into_raw();
170 c.send(<C::R as Repr<u8>>::from($e)).await?;
171 Ok(Chan::from_raw(c))
172 }
173
174
175 choose_offer!($choose; $e + 1; $($ps ($ts)),* );
176 };
177
178 (offer_body $ext:ident $t:ident $c:ident ; $e:expr ; ) => {
181 Err(Error::ConvertErr)
182 };
183 (offer_body $ext:ident $t:ident $c:ident ; $e:expr ; $p:ident $(, $ps:ident)* ) => {
184 if ($t == $e) {
185 Ok($ext::$p(Chan::from_raw($c)))
186 } else {
187 choose_offer!(offer_body $ext $t $c ; $e + 1 ; $( $ps ),*)
188 }
189 };
190
191 ($offer:ident $ext:ident; $($p:ident $t:ty),+) => {
192
193 pub enum $ext<E, C: RawChan> {
194 $( $p(Chan< $t, E, C>) ),*
195 }
196
197 impl<E, C: RawChan> OfferExt< $offer, E> for Chan< $offer, E, C>
198 where
199 C::R: Repr<u8>,
200 {
201 type C = C;
202 type OfferChan = $ext<E, Self::C>;
203
204 type OfferFuture = impl std::future::Future<Output = Result<Self::OfferChan, Error>> + 'static where Self:'static;
205 fn offer(self) -> Self::OfferFuture {
206 let mut c = self.into_raw();
207 async move {
208 let r = c.recv().await.map_err(|_| Error::RecvErr)?;
209 let t: u8 = Repr::try_into(r).map_err(|_| Error::ConvertErr)?;
210 choose_offer!(offer_body $ext t c ; 0 ; $( $p ),* )
211 }
212 }
213 }
214 };
215}
216
217pub trait OfferExt<P: HasDual, E> {
218 type C: RawChan;
219 type OfferChan;
220 type OfferFuture: Future<Output = Result<Self::OfferChan, Error>> + 'static
221 where
222 Self: 'static;
223 fn offer(self) -> Self::OfferFuture;
224}
225
226pub mod mpsc;