BSER 二进制协议
watchman 中的基本 JSON 协议允许快速简便的集成。对性能要求更高的应用程序可能需要考虑使用二进制协议。
客户端发送字节序列“\x00x\x01”即可启用二进制协议。
PDU
PDU 以其长度作为编码整数为前缀。 这允许对等方确定读取和解码它需要多少存储空间。
数组
数组由 0x00
字节值指示,后跟一个整数值,指示后面的项目数。 然后每个项目依次编码。
对象
对象由 0x01
字节值指示,后跟一个整数值,指示对象中的属性数量。 然后每个键/值对依次编码。
字符串
字符串由 0x02
字节值指示,后跟一个整数值,指示字符串中的字节数,后跟字符串的字节。
编码
与 JSON 不同,字符串未定义为具有任何特定的编码; 它们作为二进制字符串传输。 这是因为底层文件系统 API 没有为名称定义任何特定的编码。
例外: 由 watchman 命令定义的对象中的键始终为 ASCII。 一般来说,对象中的键始终为 UTF-8。
理由: 像 Python 3 这样的几种编程语言期望所有文本都使用特定的编码,并且不方便传入字节串或其他编码。 此外,不定义编码的主要目的是文件名并不总是有一个,并且文件名不太可能显示为键。
整数
所有整数都是有符号的,并以运行 watchman 守护程序的系统的主机字节顺序传输。
0x03
表示 int8_t。 后面是 int8_t 值。0x04
表示 int16_t。 后面是 int16_t 值。0x05
表示 int32_t。 后面是 int32_t 值。0x06
表示 int64_t。 后面是 int64_t 值。
实数
实数由 0x07
字节指示,后跟 8 个字节的双精度值。
布尔值
0x08
表示布尔真0x09
表示布尔假
Null
0x0a
表示 null 值
模板化对象数组
0x0b
表示后面紧跟着一个紧凑的对象数组。 watchman 返回的一些较大的数据结构是以对象数组形式表示的表格数据。 这种序列化类型将重复的对象键分解为列出键的标头数组,然后是一个包含对象所有值的数组。
为了表示模板化数组中缺少的键,可以存在 0x0c
编码值。 如果遇到,则将其解释为表示在此位置本应解码的键没有值。 这与 null 值不同。
例如
[
{"name": "fred", "age": 20},
{"name": "pete", "age": 30},
{"age": 25 },
]
表示类似于
["name", "age"],
[
"fred", 20,
"pete", 30,
0x0c, 25
]
精确的序列是
0b template
00 array -- start prop names
0302 int, 2 -- two prop names
02 string -- first prop "name"
0304 int, 4
6e616d65 "name"
02 string -- 2nd prop "age"
0303 int, 3
616765 "age"
0303 int, 3 -- there are 3 objects
02 string -- object 1, prop 1 name=fred
0304 int, 4
66726564 "fred"
0314 int 0x14 -- object 1, prop 2 age=20
02 string -- object 2, prop 1 name=pete
0304 int 4
70657465 "pete"
031e int, 0x1e -- object 2, prop 2 age=30
0c skip -- object 3, prop 1, not set
0319 int, 0x19 -- object 3, prop 2 age=25
注意:为了避免恶意的“解压缩炸弹”,Watchman 将拒绝解析具有空键集的模板对象。