演習: Protobufの解析

この演習では、protobuf バイナリ エンコード用のパーサーを作成します。見かけよりも簡単ですので、心配はいりません。これは、データのスライスを渡す一般的な解析パターンを示しています。基になるデータ自体がコピーされることはありません。

protobuf メッセージを完全に解析するには、フィールド番号でインデックス付けされたフィールドの型を知る必要があります。これは通常、proto ファイルで提供されます。この演習では、フィールドごとに呼び出される関数の match ステートメントに、その情報をエンコードします。

次の proto を使用します。

message PhoneNumber { optional string number = 1; optional string type = 2; } message Person { optional string name = 1; optional int32 id = 2; repeated PhoneNumber phones = 3; }

proto メッセージは、連続するフィールドとしてエンコードされます。それぞれが後ろに値を伴う「タグ」として実装されます。タグにはフィールド番号(例: Person メッセージの id フィールドには 2)と、バイト ストリームからペイロードがどのように決定されるかを定義するワイヤータイプが含まれます。

タグを含む整数は、VARINT と呼ばれる可変長エンコードで表されます。幸いにも、parse_varint は以下ですでに定義されています。また、このコードでは、Person フィールドと PhoneNumber フィールドを処理し、メッセージを解析してこれらのコールバックに対する一連の呼び出しに変換するコールバックも定義しています。

残る作業は、parse_field 関数と、Person および PhoneNumberProtoMessage トレイトを実装するだけです。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Speaker Notes

This slide and its sub-slides should take about 30 minutes.
  • In this exercise there are various cases where protobuf parsing might fail, e.g. if you try to parse an i32 when there are fewer than 4 bytes left in the data buffer. In normal Rust code we’d handle this with the Result enum, but for simplicity in this exercise we panic if any errors are encountered. On day 4 we’ll cover error handling in Rust in more detail.