跳到主要内容

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 将拒绝解析具有空键集的模板对象。