You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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和TokioAsyncReadCompatExt trait,用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:57:46