ピュア R で MessagePack for R を作ってみた(unpack のみ)

MessagePack をご存知の方も多いかと思います。
ざっくり説明すると、サイズがコンパクトで、かつシリアライズ・デシリアライズを高速に行うことができる言語に依存しないデータ形式です。・・・という理解です。
有志によって様々な言語でも実装が行われていることも特徴かと思います。

っで、前々から気になっていたんですが、R でのサポートがないんですよね!
「このデータ集計しといて」とデータを渡されたと思ったらデータ形式が MessagePack だった!1なんてこと日常茶飯事ですよね!!

というわけで、ピュア R で unpack だけ実装してみました!ピュア R なのは C/C++ が書けないからです><
MessagePack for R (support only unpack)

使い方

Gist から msgpack.R をダウンロードして source でロードしても良いですが、devtools の source_url なら https もロードできるようなので、ちょっと試すだけであれば source_url 経由でロードするのもありかもしれません。

データをデシリアライズするにはデータを msgpack$unpack 関数に渡します。

> library(devtools)
> source_url("https://raw.github.com/gist/4433343/msgpack.R")
text_content() deprecated. Use content(x, as = 'text')
> msgpack$unpack("\x93\x01\x02\x03")
[1] 1 2 3
> msgpack$unpack(c(charToRaw("\xCD\x01"), as.raw(0x00)))
[1] 256

上記の例では配列のデータと uint 16 のデータをデシリアライズしています。関数に渡すデータは character か raw のいずれかを想定しています。
残念なことに R では文字列に NULL 文字を含めることができないので2、NULL 文字を含むデータを直接与える場合は raw で与える必要があります。

また、ファイルからデータを読み込む場合は readBin を使います。
例えば data.msg というバイナリデータを読み込んでデシアライズしたい場合は次のようにします。

> filename <- "data.msg"
> # data.msg の作成
> system(sprintf("ruby -rmsgpack -e 'File.binwrite(\"%s\", [1,2,3].to_msgpack)'", filename))
> (binary <- readBin(filename, "raw", n = file.info(filename)$size))
[1] 93 01 02 03
> msgpack$unpack(binary)
[1] 1 2 3

以上、msgpack.R の使い方でした!
テストも適当だしパフォーマンスも意識してないのでその辺はご了承ください。
そのうち C/C++ の勉強も兼ねてちゃんとしたものを作るかもです。

ちなみに MessagePack の仕様はこちらにわかりやすく書かれているので、とりあえず動くものであれば誰でも簡単に実装できると思いますよ!

  1. そういえば拡張子は何なんですかね?古橋さんのブログで .mpac というコメントを見つけましたが。 2013/1/9 追記: 古橋さんより、最近は .msg が良いと思っているとのコメントをいただきました! 

  2. “a\x00b” はエラー、”a\u0000b” は “a” になってしまいます・・・