1use crate::{
2 channel::{Either, Transport},
3 Channel,
4};
5use anyhow::{bail, Result};
6use std::{fmt::Debug, marker::PhantomData};
7
8pub struct Tx<Role, T, Cont> {
10 pub(crate) cont: Cont,
11 _ph: PhantomData<(Role, T)>,
12}
13impl<Role, T: Send + 'static, Cont> Tx<Role, T, Cont> {
14 pub fn send<Tr: Transport>(self, channel: &mut Channel<Role, Tr>, value: T) -> Result<Cont> {
15 channel.send(self, value)
16 }
17}
18impl<Role, T, Cont: Default> Default for Tx<Role, T, Cont> {
19 fn default() -> Self {
20 Self {
21 cont: Cont::default(),
22 _ph: PhantomData,
23 }
24 }
25}
26
27pub struct Rx<Role, T, Cont> {
29 pub(crate) cont: Cont,
30 _ph: PhantomData<(Role, T)>,
31}
32impl<Role, T: Debug + 'static, Cont> Rx<Role, T, Cont> {
33 pub fn recv<Tr: Transport>(self, channel: &mut Channel<Role, Tr>) -> Result<(T, Cont)> {
34 channel.recv(self)
35 }
36}
37impl<Role, T, Cont: Default> Default for Rx<Role, T, Cont> {
38 fn default() -> Self {
39 Self {
40 cont: Cont::default(),
41 _ph: PhantomData,
42 }
43 }
44}
45
46#[derive(Default, Debug)]
49pub struct End;
50
51pub enum ChoiceResult<T1, C1, T2, C2> {
53 One(T1, C1),
54 Two(T2, C2),
55}
56
57pub struct Choice<Role1, T1, Cont1, Role2, T2, Cont2> {
62 one: Cont1,
63 two: Cont2,
64 _ph: PhantomData<(Role1, T1, Role2, T2)>,
65}
66
67impl<Role1, T1, Cont1: Default, Role2, T2, Cont2: Default> Default
68 for Choice<Role1, T1, Cont1, Role2, T2, Cont2>
69{
70 fn default() -> Self {
71 Self {
72 one: Default::default(),
73 two: Default::default(),
74 _ph: PhantomData,
75 }
76 }
77}
78
79impl<Role1, T1: 'static, Cont1, Role2, T2: 'static, Cont2>
80 Choice<Role1, T1, Cont1, Role2, T2, Cont2>
81{
82 pub fn recv<Tr: Transport>(
83 self,
84 c1: &mut Channel<Role1, Tr>,
85 c2: &mut Channel<Role2, Tr>,
86 ) -> Result<ChoiceResult<T1, Cont1, T2, Cont2>> {
87 Ok(match c1.tr.choice(&mut c1.rx, &mut c2.rx)? {
88 Either::Left(v) => match v.downcast::<T1>() {
89 Ok(v) => ChoiceResult::One(*v, self.one),
90 Err(v) => bail!("got unexpected message {:?}", v),
91 },
92 Either::Right(v) => match v.downcast::<T2>() {
93 Ok(v) => ChoiceResult::Two(*v, self.two),
94 Err(v) => bail!("got unexpected message {:?}", v),
95 },
96 Either::Both(v) => match v.downcast::<T1>() {
97 Ok(v) => ChoiceResult::One(*v, self.one),
98 Err(v) => match v.downcast::<T2>() {
99 Ok(v) => ChoiceResult::Two(*v, self.two),
100 Err(v) => bail!("got unexpected message {:?}", v),
101 },
102 },
103 })
104 }
105}