🎃

RustでMessagePackつかう

2024/01/28に公開

MessagePackで構造体をシリアライズをする方法のメモ。
調べると海外ニキの古い記事ばかりで全然欲しい情報が出てこなかったので、公式のドキュメントから持ってきた情報をここに置いておきます。

まず、下記のように適当なプロジェクトに適当な構造体があるとします。

cargo.toml
[package]
name = "hoge"
version = "0.1.0"
edition = "2021"

[dependencies]
rmp-serde = "1.1.2"
serde = { version = "1.0.188", features = ["derive"] }
hoge.rs
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Human {
  age: u32,
  name: String
}

作った構造体のderiveにSerialize, Deserializeを付すことでシリアライズ対象にすることができます。

さて、この先ですが、シリアライズのやり方を調べるといろいろな方法が出てきて混乱します。なぜ同じことをするのにいろいろな道筋を作ってしまったのか今のところ理解できていないですが、とりあえず以下のようにやればシリアライズができます。

main.rs
use std::str::FromStr;
use rmp_serde;

fn main() {
  
  let human = Human {
    age: 30,
    name: String::from_str("hogehoge").unwrap()
  };

  // encode (array format)
  let array = rmp_serde::to_vec(&human).unwrap();
  println!("len={}, data={:?}", array.len(), array);

  // encode (map format)
  let map = rmp_serde::to_vec_named(&human).unwrap();
  println!("len={}, data={:?}", map.len(), map);

  // decode
  let data: Human = rmp_serde::from_slice(&map).unwrap();
  println!("original data={:?}", data);

}

シリアライズオプションごとに2通り出しています。一つ目は配列形式(key-valueのvalueだけ)、二つ目はマップ形式(key-valueを保持したまま)。簡単ですね。

出力を見てみましょう。

len=11, data=[146, 30, 168, 104, 111, 103, 101, 104, 111, 103, 101]
len=20, data=[130, 163, 97, 103, 101, 30, 164, 110, 97, 109, 101, 168, 104, 111, 103, 101, 104, 111, 103, 101]
original data=Human { age: 30, name: "hogehoge" }

シリアライズしたデータはバイナリなのでそのまま出すと何のこっちゃですが、データサイズが異なっているのでうまくいってるでしょう(適当)。デシリアライズでオリジナルデータの復元もできてますね。おしまい。

参考サイト
rmp_serde::encode - Rust

Discussion