Trait wrpc_transport::invoke::Invoke

source ·
pub trait Invoke: Send + Sync {
    type Context: Send + Sync;
    type Outgoing: AsyncWrite + Index<Self::Outgoing> + Send + Sync + Unpin + 'static;
    type Incoming: AsyncRead + Index<Self::Incoming> + Send + Sync + Unpin + 'static;

    // Required method
    fn invoke<P>(
        &self,
        cx: Self::Context,
        instance: &str,
        func: &str,
        params: Bytes,
        paths: impl AsRef<[P]> + Send,
    ) -> impl Future<Output = Result<(Self::Outgoing, Self::Incoming)>> + Send
       where P: AsRef<[Option<usize>]> + Send + Sync;
}
Expand description

Client-side handle to a wRPC transport

Required Associated Types§

source

type Context: Send + Sync

Transport-specific invocation context

source

type Outgoing: AsyncWrite + Index<Self::Outgoing> + Send + Sync + Unpin + 'static

Outgoing multiplexed byte stream

source

type Incoming: AsyncRead + Index<Self::Incoming> + Send + Sync + Unpin + 'static

Incoming multiplexed byte stream

Required Methods§

source

fn invoke<P>( &self, cx: Self::Context, instance: &str, func: &str, params: Bytes, paths: impl AsRef<[P]> + Send, ) -> impl Future<Output = Result<(Self::Outgoing, Self::Incoming)>> + Send
where P: AsRef<[Option<usize>]> + Send + Sync,

Invoke function func on instance instance

Note, that compilation of code calling methods on Invoke implementations within Send async functions may fail with hard-to-debug errors due to a compiler bug: https://github.com/rust-lang/rust/issues/96865

The following fails to compile with rustc 1.78.0:

use core::future::Future;

fn invoke_send<T>() -> impl Future<Output = anyhow::Result<(T::Outgoing, T::Incoming)>> + Send
where
    T: wrpc_transport::Invoke<Context = ()> + Default,
{
    async { T::default().invoke((), "compiler-bug", "free", "since".into(), [[Some(2024)].as_slice(); 0]).await }
}
async { T::default().invoke((), "compiler-bug", "free", "since".into(), [[Some(2024)].as_slice(); 0]).await }
|     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `AsRef` is not general enough
 |
 = note: `[&'0 [Option<usize>]; 0]` must implement `AsRef<[&'1 [Option<usize>]]>`, for any two lifetimes `'0` and `'1`...
 = note: ...but it actually implements `AsRef<[&[Option<usize>]]>`

The fix is to call send provided by send_future::SendFuture, re-exported by this crate, on the future before awaiting:

use core::future::Future;
use wrpc_transport::SendFuture as _;

fn invoke_send<T>() -> impl Future<Output = anyhow::Result<(T::Outgoing, T::Incoming)>> + Send
where
    T: wrpc_transport::Invoke<Context = ()> + Default,
{
    async { T::default().invoke((), "compiler-bug", "free", "since".into(), [[Some(2024)].as_slice(); 0]).send().await }
}

Object Safety§

This trait is not object safe.

Implementors§