rust-protobuf で読み書きしてみる
rust-protobuf を使ってみる。
大まかな流れ
protoc をインストールする
Ubuntu ならこんな感じ:
sudo apt update sudo apt install protobuf-compiler
cargo build 時に proto をコンパイルするようにする
まず、コンパイルすべき proto ファイルを用意する。
以下のファイルを src/person.proto
に置く:
syntax = "proto3"; message Person { uint64 id = 1; string name = 2; }
次に、Cargo.toml
に以下を追加する:
[build-dependencies] protoc-rust = "2.0"
build.rs
というファイルを Cargo.toml と同じディレクトリ に置く:
extern crate protoc_rust; use protoc_rust::Customize; use std::error::Error; fn main() -> Result<(), Box<Error>> { let proto_files = vec!["src/person.proto"]; protoc_rust::run(protoc_rust::Args { input: &proto_files[..], out_dir: "src/protos", includes: &[], customize: Customize { ..Default::default() }, })?; Ok(()) }
ここで out_dir
に src/protos
というディレクトリを指定したので、作成しておく。
mkdir src/protos
これで proto をコンパイルする準備が整った。あとは cargo build
すればコンパイルされる。
cargo build # person.rs が生成されていることを確認 ls src/protos
コンパイルによって生成された struct を使って読み書きする
まず、Cargo.toml
に以下の dependency を追加する:
[dependencies] protobuf = "~2.0"
次に生成されたモジュールを use できるようにする。src/protos/mod.rs
を以下の内容で作成:
pub mod person;
次に main.rs
に以下を追加:
mod protos; use protos::person::Person;
これで準備は整ったのでいよいよ読み書きしていく。
書き込み
以下のように、Person::new()
で入れ物を作り、set_*
で値を入れ、write_to_writer
で書き出す。
use protobuf::Message; use std::fs::File; ... let mut person = Person::new(); person.set_id(42); person.set_name("Yusuke Nojima".to_string()); let mut file = File::create("/tmp/person.bin")?; person.write_to_writer(&mut file)?;
読み込み
デシリアライズしたいスライスを merge_from_bytes
に渡すと読み込んでくれる。
use protobuf::Message; use std::fs::File; use std::io::Read; ... let mut file = File::open("/tmp/person.bin")?; let mut buffer = vec![]; file.read_to_end(&mut buffer)?; let mut person = Person::new(); person.merge_from_bytes(&buffer[..])?;
サンプルコード
サンプルコード全体は GitHub にアップロードしたので、断片じゃなくて動作するコードが読みたい人はこっちを参照してください:
workspace/rust-protobuf-sample at master · nojima/workspace · GitHub
参考にしたページ
rust-protobuf 自体にはあまりドキュメントがないけど、C++版と使い方がかなり似ているので、本家の C++ のドキュメントが参考になった。
Protocol Buffer Basics: C++ | Protocol Buffers | Google Developers