ferrite_session/internal/session/channel/
send.rs1use tokio::{
2 task,
3 try_join,
4};
5
6use crate::internal::{
7 base::{
8 unsafe_create_session,
9 unsafe_run_session,
10 AppendContext,
11 Context,
12 ContextLens,
13 Empty,
14 PartialSession,
15 Protocol,
16 },
17 functional::{
18 App,
19 Nat,
20 },
21 protocol::SendChannel,
22};
23
24pub fn send_channel_from<C1, C2, N, A, B>(
25 _n: N,
26 cont: PartialSession<C2, B>,
27) -> PartialSession<C1, SendChannel<A, B>>
28where
29 A: Protocol,
30 B: Protocol,
31 C1: Context,
32 C2: Context,
33 N: ContextLens<C1, A, Empty, Target = C2>,
34{
35 unsafe_create_session::<C1, SendChannel<A, B>, _, _>(
36 move |ctx1, (chan_sender, provider_end)| async move {
37 let (endpoint, ctx2) = N::extract_source(ctx1);
38
39 let client_end = endpoint.get_applied();
40
41 let ctx3 = N::insert_target((), ctx2);
42
43 chan_sender.send(client_end).unwrap();
44
45 unsafe_run_session(cont, ctx3, provider_end).await;
46 },
47 )
48}
49
50pub fn receive_channel_from<C1, C2, C3, N, M, A1, A2, B>(
51 _n: N,
52 cont1: impl FnOnce(M) -> PartialSession<C3, B>,
53) -> PartialSession<C1, B>
54where
55 A1: Protocol,
56 A2: Protocol,
57 B: Protocol,
58 C1: Context<Length = M>,
59 C2: AppendContext<(A1, ()), Appended = C3>,
60 C3: Context,
61 N: ContextLens<C1, SendChannel<A1, A2>, A2, Target = C2>,
62 M: Nat,
63{
64 let cont2 = cont1(M::nat());
65
66 unsafe_create_session(move |ctx1, provider_end| async move {
67 let (endpoint, ctx2) = N::extract_source(ctx1);
68
69 let (chan_receiver, client_end2) = endpoint.get_applied();
70
71 let client_end1 = chan_receiver.recv().await.unwrap();
72
73 let ctx3 = N::insert_target(App::new(client_end2), ctx2);
74
75 let ctx4 = <N::Target as AppendContext<(A1, ())>>::append_context(
76 ctx3,
77 (App::new(client_end1), ()),
78 );
79
80 unsafe_run_session(cont2, ctx4, provider_end).await;
81 })
82}
83
84pub fn fork<A, B, C1, C2>(
97 cont1: PartialSession<C1, A>,
98 cont2: PartialSession<C2, B>,
99) -> PartialSession<C1::Appended, SendChannel<A, B>>
100where
101 A: Protocol,
102 B: Protocol,
103 C1: Context,
104 C2: Context,
105 C1: AppendContext<C2>,
106{
107 unsafe_create_session::<C1::Appended, SendChannel<A, B>, _, _>(
108 move |ctx, (chan_sender, provider_end_b)| async move {
109 let (ctx1, ctx2) = C1::split_context(ctx);
110
111 let (provider_end_a, client_end_a) = A::create_endpoints();
112
113 let child1 = task::spawn(async move {
114 unsafe_run_session(cont1, ctx1, provider_end_a).await;
115 });
116
117 chan_sender.send(client_end_a).unwrap();
118
119 let child2 = task::spawn(async move {
120 unsafe_run_session(cont2, ctx2, provider_end_b).await;
121 });
122
123 try_join!(child1, child2).unwrap();
124 },
125 )
126}