rust-protobuf で読み書きしてみる

rust-protobuf を使ってみる。

大まかな流れ

  1. protoc をインストールする
  2. cargo build 時に proto をコンパイルするようにする
  3. コンパイルによって生成された struct を使って読み書きする

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_dirsrc/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