【RUST开发】

在rust中使用Protobuf



前言

Google的Protobuf(全称Google Protocol Buffer),是一种高效轻便的结构化数据存储方式,可用于(数据)通信协议、数据存储等。优势这里就不多说了,基本上主流的程序语言都支持,性能也很强。下面讲讲在RUST里怎么用。


一、使用方法

在RUST中使用Protobuf比较简单,主要有三个步骤:
第一步:编制消息定义文件(.proto文件);
第二步:生成消息序列化文件(.rs文件);
第三步:在程序中使用对应的方法对消息进行序列化和反序列化。
其中,消息定义文件的编制规范不是本文重点,这里不做介绍,有需要的话可以查阅Google相关文档。

二、生成消息序列化文件的几种途径

RUST的文档里列举了Protobuf的三种使用途径(官方文档: protobuf_codegen):
1.通过protoc命令行配合protoc-gen-rust插件;
2.通过protobuf_codegen包使用纯RUST;
3.通过protobuf_codegen包使用protoc。
几种方式各有优劣,不存在说哪个更好,根据自己的实际情况选择就行。
其中,第一种方法需要下载protoc程序以及protoc-gen-rust插件,在命令行下执行生成RUST文件,后两种方法则通过在RUST程序中引入protobuf_codegen包来达到同样的目的。具体方法如下:

1.protoc+protoc-gen-rust插件

protobuf的安装这里不重点介绍,默认大家已经安装。如果没有安装的话资源链接在这里,大家可以自行下载编译。(Git地址: protobuf
在OS-X以及Ubuntu上也可以通过如下方式安装:
在这里插入图片描述

Windows下成功编译后可生成protoc.exe文件,在命令行执行“protoc --version”命令可以显示版本号。
在这里插入图片描述
目前protoc直接可以支持的语言有C++,java,js,c#,Python,Ruby,Objective-C,go,Dart,PHP,暂时还不包括RUST,所以我们需要安装插件。
插件的安装也很简单,直接在命令行执行:“cargo install protobuf-codegen”即可,当然,前提是你已经安装了cargo。
OK!激动人心的时刻终于来了!命令行窗口再次执行如下命令:
protoc -I= S R C D I R − − r u s t o u t = SRC_DIR --rust_out= SRCDIRrustout=DST_DIR $SRC_DIR/xxx.proto
其中:
$SRC_DIR: .proto 所在的源目录;
–cpp_out: 生成 c++ 代码;
$DST_DIR: 生成代码的目标目录;
xxx.proto: 要针对哪个 proto 文件生成接口代码。

以Google提供的addressbook.proto消息定义文件为例,生成前文件目录如下:
在这里插入图片描述
命令行窗口执行命令:
protoc -I=. --rust_out=./ ./addressbook.proto
文件夹变为:
在这里插入图片描述
生成了两个文件:addressbook.rs和mod.rs。

相较起来,在RUST中使用protobuf-codegen包的第二和第三种方法就简单很多。

2.protobuf_codegen+pure RUST

Cargo.toml中添加依赖:

[dependencies]
protobuf-codegen="3"
protobuf="3"

main.rs文件:

fn main() {
    Codegen::new()
        .pure()
        .out_dir("src/protos")
        .input("src/protos/addressbook.proto")
        .include("src/protos")
        .run_from_script();
        println!("Generate ok!");
}

其中,out_dir为rs文件输出目录,input为proto文件路径,include为proto文件所在目录。
在项目路径下执行:
cargo run,搞定!

3.protobuf_codegen+protoc

与方法2类似。
Cargo.toml中添加依赖:

[dependencies]
protobuf-codegen="3"
protobuf="3"
protoc-bin-vendored-win32="3.0.0"
protoc-bin-vendored="3.0.0"

main.rs文件:

use protobuf_codegen::Codegen;

fn main() {
    
    Codegen::new()
        .protoc()
        .protoc_path(&protoc_bin_vendored::protoc_bin_path().unwrap())
        .out_dir("src/protos/1")
        .input("src/protos/addressbook.proto")
        .include("src/protos")
        .run_from_script();

        println!("Generate ok!");
}

cargo run,搞定!
在这里插入图片描述

三、在程序中使用

1.创建工程``

命令行运行:

cargo new pb_rust

2.拷贝生成的rs消息

将前面生成的mod.rs和addressbook.rs拷贝至src文件夹:

在这里插入图片描述

3.修改Cargo.toml文件

[package]
name = "pb_rust"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
protobuf-codegen="3"
protobuf="3"

3.修改main.rs文件

测试方法为:创建一个Person结构体,序列化为字节数组,再通过字节数组反向构造出Person结构体。
这里可以先看看proto文件中结构体的定义:

syntax = "proto3";
enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

 message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
 }
  
message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;
  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

main.rs代码如下:

mod addressbook;
use protobuf::Message;

fn main() {

    let mut p=addressbook::Person::new();
    p.id=1000;
    p.email=String::from("person@163.com");
    p.name=String::from("person"); 
    
    let mut ph=addressbook::PhoneNumber::new();

    ph.number=String::from("18899996666");
    ph.type_=addressbook::PhoneType::MOBILE.into();
    p.phones.push(ph);
    
    let out_bytes: Vec<u8> = p.write_to_bytes().unwrap();

    let msg=addressbook::Person::parse_from_bytes(&out_bytes).unwrap();
    println!("id:{}",msg.id);
    println!("name:{}",msg.name);
    println!("email:{}",msg.email);
    
    println!("phone_number:{}",msg.phones[0].number);
    //println!("phone_type:{}",msg.phones[0].type_.value());
    if addressbook::PhoneType::MOBILE==addressbook::PhoneType::from(msg.phones[0].type_.unwrap())
    {
        println!("phone_type:MOBILE");

    }
}

4.编译执行文件

cargo run之后的结果:
在这里插入图片描述

总结

在c++里用过,感觉在RUST里面使用确实清爽很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值