rpc_adapter 0.1.12

English: RPC adapter for unified request handling / 中文: 统一请求处理的RPC适配器
Documentation
use bytes::Bytes;

use crate::{Response, Return};

macro_rules! args_try_into {
  ($prefix: expr, $name:expr, $args:expr, $($await:tt)*) => {{
    use log::{error, info};

    let mut prefix = $prefix.into();
    prefix += " ";
    prefix += $name;

    match $args.try_into() {
      Ok(args) => {
        let start = coarsetime::Instant::now();
        let result = Self::call(&args)$($await)*;
        let duration = start.elapsed().as_millis();
        prefix += &format!(" {duration}ms");

        match result {
           Return::Err(err) => {
             error!("{prefix} {args:?} {err}");
             Return::Response(Response {
               code: 500,
               body: err.to_string().into(),
             })
           }
           Return::Ok(r) => {
             info!("{prefix}");
             Return::Ok(r)
           }
           Return::Response(r) => {
             info!("{prefix} {}", r.code);
             Return::Response(r)
           }
        }
      },
      Err(err) => {
        error!("{prefix} parse args : {err}");
        Return::Response(Response {
          code: 500,
          body: err.to_string().into(),
        })
      }
    }
  }};
}

pub trait Call {
  type Args: std::fmt::Debug + TryFrom<Bytes>;
  type Result;

  fn call(args: &Self::Args) -> Return<Self::Result>;

  fn log_call(prefix: impl Into<String>, name: &str, args: Bytes) -> Return<Self::Result>
  where
    <<Self as Call>::Args as TryFrom<bytes::Bytes>>::Error: std::fmt::Display,
  {
    args_try_into!(prefix, name, args,)
  }
}

pub trait AsyncCall {
  type Args: std::fmt::Debug + TryFrom<Bytes>;
  type Result;

  fn call(args: &Self::Args) -> impl Future<Output = Return<Self::Result>>;

  fn log_call(
    prefix: impl Into<String>,
    name: &'static str,
    args: Bytes,
  ) -> impl std::future::Future<Output = Return<Self::Result>>
  where
    <<Self as AsyncCall>::Args as TryFrom<bytes::Bytes>>::Error: std::fmt::Display,
  {
    async move { args_try_into!(prefix, name, args, .await) }
  }
}