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
use core::{
  future::Future,
  pin::Pin,
};

use tokio::task;

use super::types::*;
use crate::internal::{
  base::{
    context::Context,
    protocol::{
      Protocol,
      ProviderEndpoint,
    },
  },
  functional::App,
};

pub fn unsafe_create_session<C, A, Cont, Fut>(
  executor: Cont
) -> PartialSession<C, A>
where
  A: Protocol,
  C: Context,
  Cont: FnOnce(C::Endpoints, A::ProviderEndpoint) -> Fut + Send + 'static,
  Fut: Future<Output = ()> + Send,
{
  let executor2: Box<
    dyn FnOnce(
        C::Endpoints,
        ProviderEndpoint<A>,
      ) -> Pin<Box<dyn Future<Output = ()> + Send>>
      + Send,
  > = Box::new(move |ctx, provider_end| {
    Box::pin(async {
      // run the executor as a separate async task to avoid stack overflow
      // due to overly deeply nested futures.
      task::spawn(async move {
        executor(ctx, provider_end.get_applied()).await;
      })
      .await
      .unwrap();
    })
  });

  PartialSession {
    executor: executor2,
  }
}

pub async fn unsafe_run_session<C, A>(
  session: PartialSession<C, A>,
  ctx: C::Endpoints,
  provider_end: A::ProviderEndpoint,
) where
  A: Protocol,
  C: Context,
{
  // task::spawn(async move {
  (session.executor)(ctx, App::new(provider_end)).await;
  // })
  // .await
  // .unwrap();
}