{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreiewqj3tyy7i3bb2sikpufx2ycspfnwuisjnhmcjnzds4gspdslpua",
    "uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3miprot7kber2"
  },
  "path": "/t/going-from-asyncwrite-to-asyncread/24130#post_1",
  "publishedAt": "2026-04-04T09:56:00.000Z",
  "site": "https://internals.rust-lang.org",
  "tags": [
    "issue"
  ],
  "textContent": "`futures-util::io::copy` provides a efficient way to write a AsyncRead into a Asyncwrite. I recently found myself in need for the other way around: I need the AsyncWrite interface to expose a AsyncRead.\n\nWell not exactly. I needed a way to go from AsyncWrite to Stream<Result> in axum to Stream big Zip files. The corresponding issue on github sparked interest from the axum developers, so I implemented a first draft. The usage currently looks like:\n\n\n    // Stream implements: Stream<Item=Result<Bytes>>\n    let stream = Stream::new(|w: Writer| async move {\n        let mut w = std::pin::pin!(w);\n        write_all(&mut w, &[42]).await?;\n        write_all(w, &[42]).await\n    });\n\n\n\nEven if I still think, that this would be very valuable in the axum project, the abstraction-level feels wrong. The implementation doesn't use any axum related code, just `Stream` and `Bytes`, so it could be used on the client side too. Imo, this fundamental building-block shouldn't be in a small standalone project, as this contributes to projects having thousands of small dependencies, which is making supply-chain security a nightmare. I struggled to find a project where it would fit.\n\nI then asked myself, if the official futures-util crate could add the difficult (unsafe) part of this conversion, by providing a `AsyncRead` from a Closure, which gets a `AsyncWrite` and returns a `Future<Output=std::io::Result<()>>` when it finishes. This would fit, as it doesn't introduce any dependencies and it is a zero-cost abstraction without any intermediate buffers.",
  "title": "Going from AsyncWrite to AsyncRead"
}