使用rkyv_codec时,如何桥接Tokio与futures-io的AsyncWrite?
问题:Tokio AsyncWrite 与 rkyv_codec 依赖的 futures-io AsyncWrite 桥接
我正尝试使用rkyv和rkyv_codec编写一个极简示例,将记录写入文件后再读回,但编译器提示Tokio的BufWriter未实现AsyncWrite——因为rkyv_codec依赖的是futures-io库的AsyncWrite trait,需要桥接两者的AsyncWrite实现。
原代码如下:
use rkyv::{AlignedVec, Archive, Archived, Deserialize, Infallible, Serialize}; use rkyv_codec::{archive_stream, RkyvWriter, VarintLength}; use tokio::{fs::File, io::BufWriter}; #[derive(Archive, Deserialize, Serialize, Debug, PartialEq, Clone)] #[archive(check_bytes)] // check_bytes is required #[archive_attr(derive(Debug))] struct Test { int: u8, string: String, option: Option<Vec<i32>>, } #[tokio::main] async fn main() { let value = Test { int: 42, string: "hello world".to_string(), option: Some(vec![1, 2, 3, 4]), }; let mut f = File::open("foo.txt").await.unwrap(); let mut bf = BufWriter::new(f); let mut w = RkyvWriter::<_, VarintLength>::new(bf); }
解决方案:使用 tokio-util 的 compat 模块
Tokio 和 futures-io 的 IO trait 不直接兼容,需要借助tokio-util库的compat模块完成桥接,具体步骤如下:
- 添加依赖:在
Cargo.toml中添加 tokio-util 依赖并启用compat特性
[dependencies] # 保留原有的 rkyv、rkyv_codec、tokio 依赖 tokio-util = { version = "0.7", features = ["compat"] }
- 修改代码实现桥接与完整逻辑:
引入TokioAsyncWriteCompatExt和TokioAsyncReadCompatExttrait,用compat_write和compat_read方法将Tokio的IO类型转换为futures-io兼容的类型,同时补充完整的写入、读取和校验逻辑:
use rkyv::{Archive, Archived, Deserialize, Serialize}; use rkyv_codec::{RkyvReader, RkyvWriter, VarintLength}; use tokio::{fs::File, io::BufWriter, io::BufReader}; // 引入compat桥接trait use tokio_util::compat::{TokioAsyncWriteCompatExt, TokioAsyncReadCompatExt}; #[derive(Archive, Deserialize, Serialize, Debug, PartialEq, Clone)] #[archive(check_bytes)] #[archive_attr(derive(Debug))] struct Test { int: u8, string: String, option: Option<Vec<i32>>, } #[tokio::main] async fn main() { let value = Test { int: 42, string: "hello world".to_string(), option: Some(vec![1, 2, 3, 4]), }; // 写入文件:使用create而非open(open是只读模式) let write_file = File::create("foo.txt").await.unwrap(); let buf_writer = BufWriter::new(write_file); // 将Tokio的BufWriter转换为futures-io兼容的AsyncWrite let mut rkyv_writer = RkyvWriter::<_, VarintLength>::new(buf_writer.compat_write()); // 归档并写入数据 rkyv_writer.archive(&value).await.unwrap(); // 刷新并完成写入 let compat_writer = rkyv_writer.into_inner().await.unwrap(); compat_writer.await.unwrap(); // 读取文件 let read_file = File::open("foo.txt").await.unwrap(); let buf_reader = BufReader::new(read_file); // 将Tokio的BufReader转换为futures-io兼容的AsyncRead let mut rkyv_reader = RkyvReader::<_, VarintLength>::new(buf_reader.compat_read()); // 加载归档数据并反序列化 let archived_data = rkyv_reader.load().await.unwrap(); let restored_value: Test = archived_data.deserialize(&mut ()).unwrap(); // 验证读取结果与原数据一致 assert_eq!(restored_value, value); println!("数据读写成功:{:?}", restored_value); }
关键说明
compat_write:将Tokio实现的AsyncWrite转换为futures-io定义的AsyncWrite,满足rkyv_codec的要求compat_read:同理处理读取端,将Tokio的AsyncRead转换为futures-io的AsyncRead- 原代码中
File::open是只读模式,写入操作需改为File::create或File::create_new
内容的提问来源于stack exchange,提问作者JACK M
相关产品推荐
相关产品推荐

