Turn Stream+Sink back into AsyncRead+AsyncWrite

Hi!

I can't figure out how to turn a Framed stream into something that again implements AsyncWrite and AsyncRead.

Here's a minimized version of the code that I'd like to compile (Playground link):

use bytes::Bytes;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::codec::{Decoder, Encoder, Framed};
use tokio_util::io::{SinkWriter, StreamReader};

// takes a stream and wraps it with encryption
// doesn't compile :-(
fn handshake(stream: impl AsyncRead + AsyncWrite) -> impl AsyncWrite + AsyncRead {
    SinkWriter::new(StreamReader::new(Framed::new(
        stream,
        NoiseCodec),
    ))
}

struct NoiseCodec;

impl<'a> Encoder<&'a [u8]> for NoiseCodec {
    type Error = std::io::Error;

    fn encode(
        &mut self,
        item: &'a [u8],
        dst: &mut tokio_util::bytes::BytesMut,
    ) -> std::result::Result<(), Self::Error> {
        todo!() // encrypt stuff
    }
}

impl Decoder for NoiseCodec {
    type Item = Bytes;

    type Error = std::io::Error;

    fn decode(
        &mut self,
        src: &mut tokio_util::bytes::BytesMut,
    ) -> std::result::Result<Option<Self::Item>, Self::Error> {
        todo!() // decrypt stuff
    }
}

Another attempt at implementing this using futures' split function Playground link:

fn handshake(stream: impl AsyncRead + AsyncWrite) -> (impl AsyncWrite, impl AsyncRead) {
    let (wr, rd) = Framed::new(
        stream, NoiseCodec,
    ).split();
    (SinkWriter::new(wr), StreamReader::new(rd))
}

This also doesn't work due to a lifetime not being general enough.


However this works (Playground link):

fn make_writer(stream: impl AsyncRead + AsyncWrite) -> impl AsyncWrite {
    SinkWriter::new(Framed::new(
        stream,
        NoiseCodec),
    )
}

fn make_reader(stream: impl AsyncRead + AsyncWrite) -> impl AsyncRead {
    StreamReader::new(Framed::new(
        stream,
        NoiseCodec),
    )
}

But I need to be able to read and write.

Thanks for any help in advance!

Solved: it's fixed in a not yet released version of tokio-util: io: fix trait bounds on impl Sink for StreamReader (#6647) · tokio-rs/tokio@ed4ddf4 · GitHub

1 Like