scodecでmsgpackライブラリを作ってみた
pocketberserker/scodec-msgpack · GitHub
名前は特に思いつかなかったのでそのまんまです。
実装理由
- scalazフレンドリーなmsgpackライブラリがほしかった(建前)
- scodecの勉強のため
- そろそろ一度はscalaのライブラリレベルのコード書かないとなーと思っていた(本音)
必要なもの
scodecに依存しているので、scodecに関連する知識が必要です。具体的には、
- scodec-bits
- scalazの一部(少なくともEither)
- shaplessの一部(HListの使い方は必須。Genericも知っていると便利?)
とかです。
まぁ、Eitherは難しくないですしshapelessもHListを使うことに限れば理解するのに何日もかからないと思うので、そんなにこわくないはずです。
使い方
極力scodecと同じように書けるようにしたつもりです。
import scodec._ case class Point(x: Int, y: Int, z: Int) val pointCodec = (msgpack.int :: msgpack.int :: msgpack.int).as[Point] val encoded: String \/ BitVector = pointCodec.encode(Point(-5, 1024, 1)) // \/-(BitVector(40 bits, 0xfbcd040001)) val decoded: String \/ Point = pointCodec.decode(BitVector(0xfb, 0xcd, 0x04, 0x00, 0x01)) // \/-(Point(-5,1024,1))
pointCodec
の中身がint8
ではなくmsgpack.int
なのが重要な点です。
考えないといけないこと
- extを楽に生成することができない
- 無駄にimplicitを使ってしまっている気がするので外す
- Map周りがこれでいいのかわからない
- IndexedSeqをVectorに差し替えるかも
- case classからjson styleにマッピングする関数を作るかどうか
- パフォーマンス調査
実装時に困ったこと
scodecを調べながらだったので結構時間がかかってしまいました。 README、テストコード、ブログ、最終的にソースコードと読んでいったのでこの作業で2,3日使ったような…?
なお、CodecがMonadでないことはねこはるさんとxuwei-kさんに教えていただきました。ありがとうございました。
あとはScalaの作法がわからず困ったとか、そんな感じです。
おわりに
scodecのコードはわりと読みやすいと思います(Argonautに比べて、ですが)。 その影響で解説記事を書く気力がおきない…ので、情報がほしい方は私に「記事の進捗どうですか」と連呼してください。