1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

use std::pin::Pin;
use std::future::Future;
use async_std::sync::Sender;

use crate::base::protocol::{ Protocol };
use crate::base::context::{ Context };

/// A session builder is a consumer for the given list of
/// input context and output a protocol with given Out type.
pub type Session < P > =
  PartialSession < (), P >;

pub struct PartialSession
  < C, A >
where
  A: Protocol,
  C: Context
{
  executor : Box <
    dyn FnOnce( C::Endpoints, Sender < A > )
      -> Pin < Box < dyn Future < Output=() > + Send > >
    + Send
  >
}

pub fn unsafe_create_session
  < I, P, Fut >
  (
    executor : impl
      FnOnce( I::Endpoints, Sender < P > )
        -> Fut
      + Send + 'static
  ) ->
    PartialSession < I, P >
where
  P : Protocol,
  I : Context,
  Fut : Future < Output=() > + Send
{
  let executor2
    : Box <
        dyn FnOnce( I::Endpoints, Sender < P > )
          -> Pin < Box < dyn Future < Output=() > + Send > >
        + Send
      >
    = Box::new (
        move | ctx, sender | {
          Box::pin ( async {
            executor ( ctx, sender ).await;
          } )
        });

  PartialSession {
    executor : executor2
  }
}

pub async fn unsafe_run_session
  < C, A >
  ( session : PartialSession < C, A >
  , ctx : C :: Endpoints
  , sender : Sender < A >
  )
where
  A: Protocol,
  C: Context
{
  (session.executor)(ctx, sender).await;
}