Skip to main content

ferrite_session/internal/session/
include.rs

1use std::collections::LinkedList;
2
3use crate::internal::{
4  base::{
5    AppendContext,
6    Context,
7    ContextLens,
8    Empty,
9    PartialSession,
10    Protocol,
11    Session,
12  },
13  protocol::End,
14  session::{
15    context::append_emtpy_slot,
16    cut::{
17      AllRight,
18      Cut,
19    },
20    end::{
21      terminate,
22      wait,
23    },
24  },
25};
26
27pub fn include_session<C1, C2, N, A, B>(
28  session: Session<A>,
29  cont: impl FnOnce(N) -> PartialSession<C2, B>,
30) -> PartialSession<C1, B>
31where
32  A: Protocol,
33  B: Protocol,
34  C1: Context<Length = N>,
35  C2: Context,
36  C1: AppendContext<(A, ()), Appended = C2>,
37{
38  AllRight::cut(session, cont)
39}
40
41pub fn wait_session<I, P>(
42  session1: Session<End>,
43  cont: PartialSession<I, P>,
44) -> PartialSession<I, P>
45where
46  P: Protocol,
47  I: Context,
48  I: AppendContext<(End, ())>,
49  I: AppendContext<(Empty, ())>,
50  I::Length: ContextLens<
51    <I as AppendContext<(End, ())>>::Appended,
52    End,
53    Empty,
54    Target = <I as AppendContext<(Empty, ())>>::Appended,
55  >,
56{
57  include_session(session1, move |chan| wait(chan, append_emtpy_slot(cont)))
58}
59
60pub fn wait_sessions<I, P>(
61  sessions: Vec<Session<End>>,
62  cont: PartialSession<I, P>,
63) -> PartialSession<I, P>
64where
65  P: Protocol,
66  I: AppendContext<(End, ())>,
67  I: AppendContext<(Empty, ())>,
68  I::Length: ContextLens<
69    <I as AppendContext<(End, ())>>::Appended,
70    End,
71    Empty,
72    Target = <I as AppendContext<(Empty, ())>>::Appended,
73  >,
74{
75  wait_session(join_sessions(sessions), cont)
76}
77
78pub fn join_sessions(sessions: Vec<Session<End>>) -> Session<End>
79{
80  do_join_sessions(sessions.into_iter().collect())
81}
82
83fn do_join_sessions(mut sessions: LinkedList<Session<End>>) -> Session<End>
84{
85  match sessions.pop_front() {
86    Some(session) => include_session(session, move |c1| {
87      include_session(do_join_sessions(sessions), move |c2| {
88        wait(c1, wait(c2, terminate()))
89      })
90    }),
91    None => terminate(),
92  }
93}