MessagePack C# 実装を作ってみた

Notice: こちらのエントリに、より新しいバージョンについての記述があります

MessagePack の PHP(PECL) 版の実装を作ろうと思っていたのだが、諸般の事情もあって .net/mono 版を急ぎたかったので、とりあえず C# でさっさか実装してみた。ひとしきりの UnitTest は書いてあるので、ある程度以上にはまともに動くはずである。

ソースコードとバイナリ

レポジトリルート: Source | SVN | Assembla
レポジトリの tag: Source | SVN | Assembla
バイナリダウンロード: Source | SVN | Assembla

さらっと説明

上にある MessagePack 実装は、シリアライズに使う値を格納するための構造体と、その構造体のシリアライズ、逆シリアライズを行う static なクラスとで成り立っている*1

struct SUtils.Serialization.SerializableValue

SerializableValue は、整数型や小数型、byte[] や SerializableValue のコレクションなどと相互変換が可能な構造体である。
MessagePack なバイト列を逆シリアライズした結果に使われたり、あるいはシリアライズする際のソースに使うことが出来たりする。

SerializableValue 構造体は、キャスト演算子を定義しているので、

SerializableValue value = 123;
int intValue = (int)value;
SerializableValue value = "hoge";
string intValue = (string)value;

のように扱うことも出来る。

また、Equals, GetHashCode, ==, != などもオーバーライドしてあるので、SerializableValue 同士を比較したり、Dictionary のキーに用いることも出来る。

static class SUtils.Serialization.msgpack.SimplePack

class SimplePack では、SerializableValue 構造体や、Int32 などの値を MessagePack エンコードしてストリームに書き込むための static メソッドが提供されている。

特に、

SimplePack.DoSimplePack( Stream, SerializableValue );

というメソッドを使うことで、SerializableValue を MessagePack してストリームに書き込むことが出来る。

Int32 などの値も SerializableValue に implict cast 可能なので、DoSimplePack メソッド一つで足りる場合がほとんどだろう。

static class SUtils.Serialization.msgpack.SimpleUnpack

class SimpleUnpack では、ストリームから MessagePack された値を一つ読み取るためのメソッドが定義されている。

特に、

SerializableValue unpackResult = SimpleUnpack.DoSimpleUnpack( Stream );

という風に DoSimpleUnpack メソッドを用いることで、ストリームから何らかの値を一つ読み取ることが出来る。

SimpleUnpack.UnpackNumeric_Int32 といったメソッドを使えば、特定の型を指定して読み取る*2ことも出来るが、やはりたいていの場合は DoSimpleUnpack で事足りる・・・はずである。

今後の予定

PHP(PECL) 版の実装を早く作りたいと思ってはいるが、一身上の都合で遅くなりそうでもある。

そこで、PECL 版の前に、C# 版実装について、

  • 各種ユーティリティメソッドの提供
    • Stream 以外からの読み書きのサポート
  • SerializableValue の小型化
    • 共用体にすることで、メモリ消費を最小化する
  • 異常系の単体テストの拡充
  • mono で UnitTest を走らせてみる
    • 動くはずなんだが・・・

といった改善をしてゆく予定である。

*1:今のところ、である。随時拡充の予定。

*2:正確に言うと、特定の CTS 上の型に変換できるはずの MessagePack された値を読み取る、となる。