Async-std, splitting reader/writer & lifetimes

Consider the following:

async_std::io::copy(&mut stream_src, &mut stream_dst);
async_std::io::copy(&mut stream_dst, &mut stream_src);

The above is doing the perfect relay between stream_src and stream_dst. Unfortunately, the above does not work unless you know that those streams are async_std::net::TcpStream. If you only have a stream that is under another layer (for example TlsStream), you have bad luck.

I have been looking for alternatives to workaround this, but I think in theory unless we have some runtime like tokio that supports split natively or we write those steams using poll time locking and Mutex, this does not seems to work - the stream have to be able to be read and write at the same time, to support all possible protocols.