merfolk_frontend_duplex 0.1.0

A `Frontend` for merfolk allowing the use of different frontends for calling and receiving.
Documentation
#![cfg_attr(not(feature = "std"), no_std)]

use std::marker::PhantomData;

use merfolk::{
  interfaces::{Backend, Frontend},
  Call, Reply,
};

use anyhow::Result;

use log::trace;

#[derive(derive_builder::Builder)]
#[builder(pattern = "owned")]
#[cfg_attr(not(feature = "std"), builder(no_std))]
pub struct Duplex<'a, B, FC, FR>
where
  B: Backend + 'a,
  FC: Frontend<Backend = B> + 'a,
  FR: Frontend<Backend = B> + 'a,
{
  #[builder(private, default = "PhantomData")]
  __phantom: PhantomData<&'a B>,

  pub caller: FC,

  pub receiver: FR,
}

impl<'a, B, FC, FR> Duplex<'a, B, FC, FR>
where
  B: Backend + 'a,
  FC: Frontend<Backend = B> + 'a,
  FR: Frontend<Backend = B> + 'a,
{
  pub fn builder() -> DuplexBuilder<'a, B, FC, FR> {
    DuplexBuilder::default()
  }
}

unsafe impl<'a, B, FC, FR> Send for Duplex<'a, B, FC, FR>
where
  B: Backend,
  FC: Frontend<Backend = B>,
  FR: Frontend<Backend = B>,
{
}

impl<'a, B, FC, FR> Frontend for Duplex<'a, B, FC, FR>
where
  B: Backend,
  FC: Frontend<Backend = B>,
  FR: Frontend<Backend = B>,
{
  type Backend = B;

  fn register<T>(&mut self, caller: T) -> Result<()>
  where
    T: Fn(Call<<Self::Backend as Backend>::Intermediate>) -> Result<Reply<<Self::Backend as Backend>::Intermediate>> + 'static + Send + Sync,
  {
    trace!("duplex caller");

    self.caller.register(caller)
  }

  #[allow(clippy::type_complexity)]
  fn receive(&self, call: Call<<Self::Backend as Backend>::Intermediate>) -> Result<Reply<<Self::Backend as Backend>::Intermediate>> {
    trace!("receive call");

    self.receiver.receive(call)
  }
}