内容提要
Preserves规范更新至0.990.0版,作者认为1.0候选版临近。主要变化是简化二进制语法:移除“短”和“中”两种SignedInteger表示,所有SignedInteger统一用0xB0标签;Float和Double改用0x87标签加长度编码,取代固定标签0x82和0x83,为未来支持其他IEEE754格式铺路。文中还以参考卡形式列出各类型值的二进制编码规则及varint编码方式。
延伸解读
二进制语法简化的取舍
0.990.0 版移除了 SignedInteger 的“短”和“中”两种表示,统一用 0xB0 标签加 varint 长度和整数字节。作者认为这些旧表示“不划算”,简化后编码规则更一致,但可能增加小整数的编码长度。读者需注意:这是规范层面的精简,实际实现需同步调整解析逻辑。
Float/Double 编码的扩展性
Float 和 Double 从固定标签 0x82、0x83 改为 0x87 加长度字节(0x04 或 0x08),为未来支持其他 IEEE754 格式(如半精度)留出空间。这种设计用少量额外字节换取格式扩展性,但解析时需先读长度再决定如何解释后续字节。
varint 与长度前缀的统一
参考卡显示,SignedInteger、String、ByteString、Symbol 等类型都使用 varint 编码长度或整数字节数。varint 对小于 128 的值用单字节,更大值用多字节。这种统一减少了标签种类,但要求实现者正确实现 varint 的变长解码,否则会影响所有带长度前缀的类型。
Q&A
Preserves 0.990.0 版本对二进制语法做了哪些主要简化?
主要简化包括:移除了 SignedInteger 的“短”和“中”两种表示(标签 0x9x/0xAx),所有 SignedInteger 统一使用标签 0xB0;Float 和 Double 改用标签 0x87 加长度编码,取代了原来的固定标签 0x82 和 0x83。
为什么 Preserves 要移除 SignedInteger 的短和中表示?
文章指出这些表示“没有发挥应有的作用”(weren't pulling their weight),因此被移除,所有 SignedInteger 现在统一用 0xB0 标签编码。
Preserves 中 Float 和 Double 的二进制编码现在是什么?
Float 编码为 [0x87, 0x04] 后跟 binary32 值;Double 编码为 [0x87, 0x08] 后跟 binary64 值。两者都使用标签 0x87 加长度,取代了旧的固定标签 0x82 和 0x83。
Preserves 二进制语法中 varint 是如何编码的?
varint 编码规则:如果 v < 128,则编码为单字节 [v];如果 v ≥ 128,则编码为 [(v & 0x7F) + 128] 后跟 varint(v >> 7)。
Preserves 中 String 和 Symbol 的二进制编码有什么区别?
String 使用标签 0xB1,后跟 varint 编码的 UTF-8 字节长度和 UTF-8 字节;Symbol 使用标签 0xB3,同样后跟 varint 编码的 UTF-8 字节长度和 UTF-8 字节。两者结构相同,仅标签不同。
Preserves 中如何编码一个字典(Dictionary)?
字典编码为 [0xB7] 后跟每个键值对的编码(«K_1» «V_1» ... «K_m» «V_m»),最后以 [0x84] 结束。