Rust 编译并使用 Protobuf

24次阅读
没有评论

共计 2475 个字符,预计需要花费 7 分钟才能阅读完成。

内容目录

Rust 编译并使用 Protobuf

必要的依赖库

安装

Cargo

cargo add prost
cargo add prost-types
cargo add --build prost-build

依赖文件

[dependencies]
prost = "0.13.4"
prost-types = "0.13.4"

[build-dependencies]
prost-build = "0.13.4"

编写 proto 文件

syntax = "proto3";

package cmd_type;

// 传输数据的指令类型
enum CmdType {
    ///// 通用
    HEARTBEAT = 0; // 心跳检测
    AUTH = 1; // 认证
    AUTH_OK = 2; // 认证通过
    AUTH_ERR = 3; // 认证失败
    CONNECT = 4; // 连接
    DISCONNECT = 5; // 断开连接
    TRANSFER = 6; // 数据传输
    OPEN_SERVER = 7; // 开启代理端口
    CLOSE_SERVER = 8; // 关闭代理端口
}
syntax = "proto3";

package meta_data;

import "google/protobuf/timestamp.proto"; // 导入时间戳消息

// 传输数据的消息定义
message TransferMessageMetaData {
  google.protobuf.Timestamp timestamp = 1; // 时间戳
  map<string,string> metaData = 2; // 元数据
}

Rust 编译并使用 Protobuf

编写 build 脚本

 在 src 同级下创建一个build.rs文件,代码如下:

use std::fs;

fn main() {
    let out_dir = "src/core";

    // 创建输出目录
    fs::create_dir_all(out_dir).unwrap();

    prost_build::Config::new()
        .out_dir(out_dir) // 指定输出目录
        .compile_protos(
            &["proto/cmd_type.proto", "proto/meta_data.proto"], // .proto 文件
            &["proto/"],                                        // 包含目录
        )
        .expect("Failed to compile .proto files");

    // 创建顶级模块
    let mod_file = format!("{}/mod.rs", out_dir);
    let mod_content = ["cmd_type.rs", "meta_data.rs"]
        .iter()
        .map(|file| format!("pub mod {};", file.trim_end_matches(".rs")))
        .collect::<Vec<_>>()
        .join("\n");

    std::fs::write(&mod_file, mod_content).unwrap();
}

build.rs通常用于在 Rust 项目编译前执行一些构建相关的任务:

  1. 设置输出目录:

    let out_dir = "src/core";

    指定了生成的 Rust 文件将被输出到 src/core 目录中。

  2. 创建输出目录:

    fs::create_dir_all(out_dir).unwrap();

    使用 create_dir_all 函数创建输出目录。如果该目录已经存在,函数不会报错。如果创建失败,会触发 unwrap() 导致程序崩溃并输出错误信息。

  3. 编译 Proto 文件:

    prost_build::Config::new()
       .out_dir(out_dir) // 指定输出目录
       .compile_protos(
           &["proto/cmd_type.proto", "proto/meta_data.proto"], // .proto 文件
           &["proto/"],                                        // 包含目录
       )
       .expect("Failed to compile .proto files");

    在这里,使用 prost_build 库配置并编译 Protocol Buffers 文件:

    • out_dir: 指定生成的 Rust 文件应放置的目录。
    • compile_protos: 第一个参数包含待编译的 .proto 文件,第二个参数指定 .proto 文件的包含目录。
    • 如果编译失败,expect 方法将输出错误消息并导致程序崩溃。
  4. 创建顶级模块文件:

    let mod_file = format!("{}/mod.rs", out_dir);

    创建一个 mod.rs 文件的路径,这是 Rust 中用于声明模块的文件。

  5. 生成模块内容:

    let mod_content = ["cmd_type.rs", "meta_data.rs"]
       .iter()
       .map(|file| format!("pub mod {};", file.trim_end_matches(".rs")))
       .collect::>()
       .join("\n");
    • 定义一个数组 ["cmd_type.rs", "meta_data.rs"],包含将生成的 Rust 文件。
    • 使用 iter() 遍历数组,并对每个文件生成模块声明,例如 pub mod cmd_type;
    • trim_end_matches(".rs") 用于去掉文件名的 .rs 后缀,确保生成的模块声明是有效的。
    • collect::<Vec<_>>() 将迭代结果收集到向量中。
    • join("\n") 将向量中的模块声明连接成单一字符串,每个模块声明之间使用换行符分隔。
  6. 写入模块文件:

    std::fs::write(&mod_file, mod_content).unwrap();

    将生成的模块内容写入到 mod.rs 文件中。如果写入过程中出现错误,unwrap() 将导致程序崩溃并显示错误信息。

    编译

     使用cargo build命令编译。

    Rust 编译并使用 Protobuf

正文完
 
PG Thinker
版权声明:本站原创文章,由 PG Thinker 2024-12-31发表,共计2475字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
热评文章
Rust 编译并使用 Protobuf

Rust 编译并使用 Protobuf

内容目录 Rust 编译并使用 Protobuf 必要的依赖库 prost: https://github.c...