Boost.Serializationの出力形式としてMessagePackを使えるようにしてみた

Boost.ArchiveのMessagePackバックエンドに用いた実装です。まだ試作段階ですが、Boost付属のSerialization用テストは一通り合格しているので、とりあえず動くと思います。

ソースコードgithubにあります。なお、ビルドツールはwafを使用しているため、ビルドにはpythonが必要です。もっとも、cppファイル2個しかありませんが。

メリット

Boostには標準でバイナリアーカイブが付属していますが、バイナリアーカイブクロスプラットフォームではありません。したがって、ネットワーク通信など、送り手と受け手の環境を一致させることが困難な状況でバイナリアーカイブは適切な選択肢ではありません。また、テキストやXMLアーカイブを使用すれば可搬性は高まりますが、データサイズが肥大化してしまいます。

MessagePackはプラットフォームに依存しないフォーマットを採用しているため、バイナリアーカイブと比較して、より広範囲にわたるデータ交換を可能にします。MessagePackは標準で一部の型(例えばstd::vector)の変換アルゴリズムを持っていますが、Boost.Serializationの枠組みに対応することにより、より多くの型をシリアライズすることができます。また、MessagePackは様々な言語でバインディングが提供されているため、他の言語とのデータ交換も可能でしょう。(ただし、Boost.Serializationの変換ルールを他の言語で実装しなければならないため、それなりの手間がかかると思いますが)

未実装

以下の機能は未実装です。

  • woarchive, wiarchive
  • wchar_t型の扱い
  • polymorphic archive

oarchive, iarchiveではwchar_t型はマルチバイト文字列に変換してからシリアライズされます。同様にwoarchive, wiarchiveではマルチバイト文字列はwchar_t型に変換してからシリアライズされますが、現時点では文字変換は未対応です。wchar_t型は数値型として、std::wstringはc_str()で得られる文字列をそのままRAW型として書き出しています。

フォーマット

基本的には、データをそのまま書き出します。

struct A {
    bool a; int b;
    template <class Archive>
    void serialize(Archive& ar) {
        ar & a & b;
    }
};
struct B {
    A a; float b;
    template <class Archive>
    void serialize(Archive& ar) {
        ar & a & b;
    }
};

というクラスがあった場合、

    msgpack::packer<Stream> p;
    B b;
    p << b.a.a << b.a.b << b.b;

とほぼ等価です。実際には、ファイル先頭にBoost.Serializationのヘッダが付与されるため、若干肥大化します。また、Name Value Pair (NVP)の名前は無視され、値のみが出力されます。