# Wrap/Bridge std::io::Read to AsyncRead

**URL:** <https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915>\
**Category:** help\
**Created:** [November 9, 2024, 6:38pm UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915 "2024-11-09T18:38:02Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tik](https://avatars.discourse-cdn.com/v4/letter/t/7ea924/32.png) [@tik](https://users.rust-lang.org/u/tik)\
**Post date:** [November 9, 2024, 6:38pm UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/1 "2024-11-09T18:38:02Z")

</div>

I'm using [interprocess](https://docs.rs/interprocess/latest/interprocess/index.html) to do ipc. This is working. I now want to develop a communication protocol using [capnp-rpc](https://docs.rs/capnp-rpc/latest/capnp_rpc/index.html) + [futures](https://docs.rs/futures/latest/futures/index.html) (as the execution environment).

Interprocess's [Stream](https://docs.rs/interprocess/latest/interprocess/local_socket/enum.Stream.html) implements std::io::Read & std::io::Write, while capnp-rpc's [twoparty::VatNetwork::new()](https://docs.rs/capnp-rpc/latest/capnp_rpc/twoparty/struct.VatNetwork.html#method.new) expects async versions (futures\_io::AsyncRead & futures\_io::AsyncWrite).

Is there a utility crate that bridges between the sync and async versions?

AsyncRead/Write from futures-io has an implementation for [Pin](https://docs.rs/futures-io/0.3.30/futures_io/trait.AsyncRead.html#impl-AsyncRead-for-Pin%3CP%3E). Could this help?

```rust
let plugin_interface_client: crate::plugin::protocol_capnp::plugin_interface::Client =
    capnp_rpc::new_client(PluginInterfaceImpl { name: "ACMEPLUGIN".to_string() });

for mut conn in listener.incoming().filter_map(handle_error) {
    let network = twoparty::VatNetwork::new(
        Pin::new(conn.as_read()),
        Pin::new(conn.as_write()),
        rpc_twoparty_capnp::Side::Server,
        Default::default(),
    );

    let rpc_system =
        RpcSystem::new(Box::new(network), Some(plugin_interface_client.clone().client));

    ...
}

```

gives en error that it needs a &mut version of Read/Write and I don't know how to get one...

```rust
error[E0277]: the trait bound `&LocalSocketStream: DerefMut` is not satisfied
   --> prototype/src/plugin/server.rs:78:17
    |
77 | let network = twoparty::VatNetwork::new(
    | ------------------------- required by a bound introduced by this call
78 | Pin::new(conn.as_read()),
    | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `DerefMut` is not implemented for `&LocalSocketStream`, which is required by `Pin<&LocalSocketStream>: AsyncRead`
    |
    = help: the trait `AsyncRead` is implemented for `Pin<P>`
    = note: `DerefMut` is implemented for `&mut LocalSocketStream`, but not for `&LocalSocketStream`
    = note: required for `Pin<&LocalSocketStream>` to implement `AsyncRead`
note: required by a bound in `capnp_rpc::twoparty::VatNetwork::<T>::new`
   --> /Users/xxx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/capnp-rpc-0.20.2/src/twoparty.rs:231:8
    |
231 | T: AsyncRead + Unpin,
    | ^^^^^^^^^ required by this bound in `VatNetwork::<T>::new`
...
243 | pub fn new<U>(
    | --- required by a bound in this associated function

```

---

<div class="post-metadata">

**Author:** ![drewtato](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/drewtato/32/32949_2.png) [@drewtato](https://users.rust-lang.org/u/drewtato)\
**Post date:** [November 9, 2024, 6:50pm UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/2 "2024-11-09T18:50:08Z")

</div>

Looks like interprocess has an async `Stream`: [Stream in interprocess::local\_socket::tokio - Rust](https://docs.rs/interprocess/latest/interprocess/local_socket/tokio/enum.Stream.html)

That implements Tokio's async traits instead of futures', but you can bridge those with [TokioAsyncReadCompatExt in tokio\_util::compat - Rust](https://docs.rs/tokio-util/latest/tokio_util/compat/trait.TokioAsyncReadCompatExt.html)

---

<div class="post-metadata">

**Author:** ![tik](https://avatars.discourse-cdn.com/v4/letter/t/7ea924/32.png) [@tik](https://users.rust-lang.org/u/tik)\
**Post date:** [November 9, 2024, 6:53pm UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/3 "2024-11-09T18:53:58Z")

</div>

Thanks! ...Just found that futures has a wrapper build in: [AllowStdIo](https://docs.rs/futures/latest/futures/io/struct.AllowStdIo.html). This seems to work.

---

<div class="post-metadata">

**Author:** ![drewtato](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/drewtato/32/32949_2.png) [@drewtato](https://users.rust-lang.org/u/drewtato)\
**Post date:** [November 9, 2024, 7:10pm UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/4 "2024-11-09T19:10:24Z")

</div>

As for why your method doesn't work:

The implementation for `Pin` is only for when the pinned type already implements `AsyncRead`, so it's not going to help. The only way to make `Read` types properly implement `AsyncRead` is by spawning a thread.

> [@tik](#):
>
> Thanks! ...Just found that futures has a wrapper build in: [AllowStdIo](https://docs.rs/futures/latest/futures/io/struct.AllowStdIo.html). This seems to work.

I wouldn't use this unless you're not actually doing something asynchronously, either by only running one future or using a `Read` type that is always ready.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/skifire13/32/17959_2.png) [@SkiFire13](https://users.rust-lang.org/u/SkiFire13)\
**Post date:** [November 9, 2024, 9:01pm UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/5 "2024-11-09T21:01:53Z")

</div>

> [@tik](#):
>
> Thanks! ...Just found that futures has a wrapper build in: [AllowStdIo](https://docs.rs/futures/latest/futures/io/struct.AllowStdIo.html). This seems to work.

You're most likely just blocking the current async task with that, which is not good if you want to write something actually async. It is supposed to be used when the underlying I/O operation will return immediately, either because it's ready or because it's in non-blocking mode and will return `io::Error::WouldBlock` if it's not ready. In the latter case you will also have to manually handle waking your task up when it can make progress, which is a pretty low-level operation.

---

<div class="post-metadata">

**Author:** ![tik](https://avatars.discourse-cdn.com/v4/letter/t/7ea924/32.png) [@tik](https://users.rust-lang.org/u/tik)\
**Post date:** [November 10, 2024, 6:24am UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/6 "2024-11-10T06:24:54Z")

</div>

> [@drewtato](#):
>
> As for why your method doesn't work:
> 
> The implementation for `Pin` is only for when the pinned type already implements `AsyncRead`, so it's not going to help. The only way to make `Read` types properly implement `AsyncRead` is by spawning a thread.

Ah, I see. Because of `<P as Deref>::Target: AsyncRead` ... I have much to learn.

---

<div class="post-metadata">

**Author:** ![tik](https://avatars.discourse-cdn.com/v4/letter/t/7ea924/32.png) [@tik](https://users.rust-lang.org/u/tik)\
**Post date:** [November 10, 2024, 6:25am UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/7 "2024-11-10T06:25:52Z")

</div>

> [@drewtato](#):
>
> > [@tik](#):
> >
> > Thanks! ...Just found that futures has a wrapper build in: [AllowStdIo](https://docs.rs/futures/latest/futures/io/struct.AllowStdIo.html). This seems to work.
> 
> I wouldn't use this unless you're not actually doing something asynchronously, either by only running one future or using a `Read` type that is always ready.

> [@SkiFire13](#):
>
> You're most likely just blocking the current async task with that, which is not good if you want to write something actually async. It is supposed to be used when the underlying I/O operation will return immediately, either because it's ready or because it's in non-blocking mode and will return `io::Error::WouldBlock` if it's not ready. In the latter case you will also have to manually handle waking your task up when it can make progress, which is a pretty low-level operation.

I don't plan to use async except that I have to, to get capnp-rpc's RpcSystem running and I intend to isolate that.

At a very high level this is what I want to do:

1. At startup, for each configured plugin:

- Spawn a child process

- Spawn a thread that executes the RpcSystem for that plugin & handles sending/receiving the requests/responses

1. Call remote functions on the plugins sequentially and synchronously.

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [February 8, 2025, 6:25am UTC](https://users.rust-lang.org/t/wrap-bridge-std-read-to-asyncread/120915/8 "2025-02-08T06:25:59Z")

</div>

Closed on February 8, 2025, 6:25am UTC

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
