rust AsyncRead和Stream互相转换

Stream转换为 AsyncRead

使用futures库的TryStreamExt::into_async_read方法

AsyncRead 转换为Stream

方法一: 包装一个自定义的stream

let stream = ByteStream(Cursor::new(b"hello world "));
struct ByteStream<R>(R);

impl<R: AsyncRead + Unpin> Stream for ByteStream<R> {
    type Item = Result<Bytes, anyhow::Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let mut bytes_buf = BytesMut::with_capacity(4096);
        match Pin::new(&mut self.0).poll_read(cx, &mut bytes_buf) {
            Poll::Ready(Ok(n)) => {
                if n == 0 {
                    Poll::Ready(None)
                } else {
                    Poll::Ready(Some(Ok(bytes_buf.freeze())))
                }
            }
            Poll::Ready(Err(err)) => Poll::Ready(Some(Err(DownloadError::IOError(Box::new(err))))),
            Poll::Pending => Poll::Pending,
        }
    }
}

方法二: 使用futures_codec库

futures_codec=“0.4.1”

 let stream = FramedRead::new(Cursor::new(b"hello world !"),BytesCodec)
    .map_ok(|bytes| bytes::Bytes::copy_from_slice(bytes.as_ref()));

方法三: 使用async_stream库的try_stream!宏

async-stream = { version = “0.3” }

 let stream=add_stream(Cursor::new(b"hello world !"));
fn add_stream<R>(
    mut reader: R,
) -> impl Stream<Item = Result<Bytes, anyhow::Error>> + Send + 'static
where
    R: AsyncRead + Unpin + Send + 'static,
{
    async_stream::try_stream! {
        async_stream::try_stream! {
        let mut bytes_buf = BytesMut::with_capacity(4096);
        while let Ok(n) = reader.read(&mut bytes_buf).await{
            if n==0{
                break;
            }
            yield  bytes_buf.split().freeze();
        }
    }
}

方法四: 使用futures库提供的unfold方法

futures = {version = “0.3” }

let stream=futures::stream::unfold(
        Cursor::new(b"hello world !"),
        |mut encoder| async move {
            let mut bytes_buf = BytesMut::with_capacity(4096);
            let result = encoder.read(&mut bytes_buf).await;
            match result{
                Ok(n)=>{
                    if n == 0 {
                        None
                    } else {
                        Some((Ok(bytes_buf.split().freeze()), encoder))
                    }
                },
                Err(e)=>{
                    Some((Err(e), encoder))
                }
            }
        });

推荐使用futures_codec

参考资料

  • https://github.com/rust-lang/futures-rs/issues/2006
  • https://jsdw.me/posts/rust-futures-tokio/
  • https://cloudflare-ipfs.com/ipfs/QmURzbuoZkGnnPuKpzQHVBe8xDfgR3tcH9f7SkAivBnnJJ/async_compression/stream/index.html
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值