文章目录
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