#MessagePackの文字列型追加において、Extended型を導入する提案
本提案は https://gist.github.com/frsyuki/5022569 https://gist.github.com/frsyuki/5022460 において提案された「バイナリ型」の構造に変更を施すものである。
##解決しようとする問題
- MessagePackへの拡張は今後行われないとしても、独自に拡張する提案が今後頻発しそう
- 拡張フォーマットは、既存のMessagePackに対して後方互換にならない(なりようがない)ため、相互運用性を損なう可能性が高い。これが問題
##提案する手法
今回文字列型とバイナリ型を導入するにあたり、型システムを拡張可能なものとし、拡張された型は、古いバージョンのcodecにおいては、バイナリとして扱われるような設計とすべき。
こうすることで、今後型の拡張が行われたとしても、旧バージョンのツールでラウンドトリップ問題が発生しないことを保証できるし、結局、ツールというものは自分の知ってる型のデータしか扱わないので、それで問題ない。
##フォーマット
https://gist.github.com/frsyuki/5022569 に以下の変更を施すべき。
0xc4-0xc9,0xd4,0xd5 FixExtended (0bytes - 7bytes extended type)
0xd6 Extended 8 (extended type) // new
0xd7 Extended 16 (extended type) // new
0xd8 Extended 32 (extended type) // new
0xd9 string 8 (String type) // new
0xda string 16 (String type) // changed from raw 16
0xdb string 32 (String type) // changed from raw 32
Extended = ExtendedTAG n-OCTETS (nは各FixExtended,Extended8,16,32で規定)
ExtendedTAG = 0x00 - binary 0xf0-0xff - private extension
全てのtypeを使い切るが、今後の拡張はExtendedTagを使って可能だし、その場合確実に後方互換性を保証できる。
###拡張例
たとえばtime_t型をTAG=0x31として追加する場合:
0xc7 0x31 0x51 0x2a 0xd5 0xb0 ; is Feb 25 03:08:32 2013 (0x512ad5b0)
たとえばShift_JIS型をTAG=0x32として追加する場合:
0xd6 0x0a 0x32 0x82 0xb1 0x82 0xf1 0x82 0xc9 0x82 0xbf 0x82 0xcd ; こんにちは
##FAQ
###Q.256個のExtendedTAGを使い切ったらどうなるか?
ExtendedTAGを1バイトとして定義しても可変長の構造として定義しても、後方互換性の観点から言うと優劣は存在しない。
なぜなら、2バイトのExtendedTAGが必要になったら、「データの先頭もExtendedTAGだよーというExtendedTAGを導入すればいい」から。その必要性がある実装は対応するだろうし、対応しない実装では、未知の型をもつバイナリとして扱われるから、後方互換性は維持される。
そこで、現時点でExtendedTAGを可変長フォーマットとして提案することで、提案がリジェクトされる可能性を危惧し、このような提案としている。
@frsyuki @kenn
個人的には 0xc1 に TinyExtended8 (つまり8バイト長のExtended) を割り振ることができると、圧縮率上がるし、拡張ポイントを完全に防げるかなぁ、と思わないでもないです。
あるいは 0xc1 を never に残す場合(僕は現時点でこちらのアプローチに賛成です)、TinyExtended を本当に 0-7 バイトに割り当てるのでいいのか、という話もあります。たとえば、0 1 2 4 6 8 10 12 のほうがいいのかもしれない。だが、歯抜けになるのも良くないよねという(特に小さいデータほど圧縮効率が悪くなるのは、データ型の分布を事前に予測できないというのであれば避けるべきですから)。