party_types/
protocol.rs

1use crate::{
2    channel::{Either, Transport},
3    Channel,
4};
5use anyhow::{bail, Result};
6use std::{fmt::Debug, marker::PhantomData};
7
8/// Receive a value T from the given Role
9pub 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
27/// Send a value T to the given Role
28pub 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/// End this protocol. It is good practice to demand this result from the execution
47/// to prove that the protocol ran in full.
48#[derive(Default, Debug)]
49pub struct End;
50
51/// This value is received when the choice is resolved.
52pub enum ChoiceResult<T1, C1, T2, C2> {
53    One(T1, C1),
54    Two(T2, C2),
55}
56
57/// This node allows receiving from either R1 or R2, depending on an external choice.
58///
59/// The choice is modeled as a tuple on the sender side. The `Other` is either another
60/// `Choice` or `End`.
61pub 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}