少し前にこんなのを書きましたが
ScalaJSを使ってブラウザ上のみでJSONからMessagePackに変換するやつを作った
「msgpackって当然pureなjavascript実装もあるよね?」
↓
「scala-jsから当然javascript呼べるよね?」(逆にjsからscala-js呼ぶでもいいけど)
↓
「つまりscala-js版のscodec-msgpackでシリアライズして他のjsのライブラリでデシリアライズ、またはその逆、などができるはずだよね?そして両方の実装が正しいなら、それをやっても必ず元に戻るはずだよね?」
と、思いつきやってみたという記録です。
なお、執筆時点のscala-js 0.6.5時点の記録なので、そのうち古くなるかもしれません。
まずmsgpackというよりscalajsやsbtの話
scala-jsから外部のjavascriptファイル呼び出しするためのsbtの設定
に関しては、公式に書いてあるので、それを読もう
http://www.scala-js.org/doc/project/dependencies.html
webjarなどで管理されてるものなら、1行jsDependenciesというkeyに追加でいけるらしい。
今回はそうではなく、とりあえず単一のjsファイルを半手動ダウンロードして追加したかったので、別の方法。
sbt上でのリソースのディレクトリに追加後、以下のように書くらしい。
jsDependencies += ProvidedJS / "myJSLibrary.js"
sbt上でのリソースディレクトリは、src/main/resourcesでもresourceManagedのKeyによる自動生成用ディレクトリでもどちらでもいいらしいので、手動で置く方ではなく、自動生成用を使った。
あと、これが一番ハマったのだが、なぜか
commonJSName "msgpack"
みたいに書かないといけなかった(詳細は面倒になって理解してない)。詳細知りたい人は、以下のstack overflowの回答と、そこからのscala-jsの該当issueやpull req見ましょう
scala-js側からの呼び出し
基本的な情報は公式サイトまとまってるし、今回は大体これで十分だった
http://www.scala-js.org/doc/interoperability/types.html
ちゃんとjs.Objectというものを継承したやつを作るなど、いくつか方法があるが、今回はべつにそこは丁寧に頑張りたくないため*1、雑にキャストしたりした
結論としては、以下のjsのpackという関数を呼び出すためのscala-jsのコードがこんな感じ
js.Dynamic.global.msgpack.msgpack.pack(i.asInstanceOf[js.Any]).asInstanceOf[js.Array[Int]]
さて、ここからがmsgpackな話
まずは公式のmsgpack organizationにある
https://github.com/msgpack/msgpack-javascript *2
について試したのですが、失敗します。*3
https://github.com/xuwei-k/scodec-msgpack/commit/2d6c93bf806a52fad6cc8351c
大雑把には
- msgpack-javascriptがバグってる?
- scodec-msgpackがバグってる?
- どちらもバグってないけど、テストの書き方が悪い?
のどれかだと思うのですが、詳細把握できてません。ただ、
「msgpack-javascriptでシリアライズして、msgpack-javascriptでデシリアライズ」をしても元に戻らないケースがある?ので、msgpack-javascript自体のバグの可能性が高いのでは?という気がしています。
バグってませんでした
さて、msgpack-liteという、べつのjs実装も試しました
- http://qiita.com/kawanet/items/f800c0eb37c1cb683918
- https://github.com/kawanet/msgpack-lite
- https://github.com/xuwei-k/scodec-msgpack/compare/xuwei-k:2d6c93b...xuwei-k:19162bb
最初、jvmというかそれを受け継いたscala-jsのByteのセマンティクスの違い*4に悩まされた(結局0xffとの論理積をとってunsignedとして扱うコード入れないといけない?)
けど、その0xffとの論理積さえ入れればうまくいったので、いよいよmsgpack-javascriptがダメな可能性が高まった気がします・・・。 バグってませんでした
ここまでやって、若干飽きたので、誰かこの続き調査してください(ぇ
あと色々補足情報としては
- テストはもちろん(?) scalacheckでやってます
- まだIntしかテストしてません
- テスト失敗するケースはtravis-ciみれば出ているはずなのでそれ見てね https://travis-ci.org/xuwei-k/scodec-msgpack/builds/98802427
といったところでしょうか
追記: