ipc_channel_adapter 0.1.2

Provides a utility for fast cross process communication
Documentation
use std::marker::PhantomData;
use std::fmt::Debug;

use serde::de::DeserializeOwned;
use serde::Serialize;
use tokio::sync::mpsc::unbounded_channel;
use tokio::sync::mpsc::UnboundedReceiver;
use tokio::sync::mpsc::UnboundedSender;

use crate::context::IpcClientRequestContext;
use crate::context::IpcClientResponseContext;
use crate::ipc::asynch::create_ipc_child;

pub struct HostReceiver<Request, Response>
where
  Request: Clone + Send + Serialize + DeserializeOwned + Debug + 'static,
  Response: Clone + Send + Serialize + DeserializeOwned + Debug + 'static,
{
  _0: PhantomData<Request>,
  _1: PhantomData<Response>,
}

impl<Request, Response> HostReceiver<Request, Response>
where
  Request: Clone + Send + Serialize + DeserializeOwned + Debug + 'static,
  Response: Clone + Send + Serialize + DeserializeOwned + Debug + 'static,
{
  pub fn new(
    channel_name: &str,
  ) -> Result<
    (
      Self,
      UnboundedReceiver<(Request, UnboundedSender<Response>)>,
    ),
    (),
  > {
    let ipc_child_client = channel_name.to_string();
    let (tx, rx) = unbounded_channel::<(Request, UnboundedSender<Response>)>();

    tokio::spawn(async move {
      let Ok((tx_ipc, mut rx_ipc)) = create_ipc_child::<
        IpcClientResponseContext<Response>,
        IpcClientRequestContext<Request>,
      >(&ipc_child_client) else {
        return;
      };

      while let Some(data) = rx_ipc.recv().await {
        let (tx_reply, mut rx_reply) = unbounded_channel::<Response>();
        tx.send((data.1, tx_reply)).unwrap();
        let response = rx_reply.recv().await.unwrap();
        if tx_ipc
          .send(IpcClientResponseContext::<Response>(data.0, response))
          .is_err()
        {
          return;
        };
      }
    });

    Ok((
      Self {
        _0: PhantomData {},
        _1: PhantomData {},
      },
      rx,
    ))
  }
}