Skip to main content

3. CBOR 编码规范 (Specification of the CBOR Encoding)

CBOR 数据项 (第2节) 按照本节描述的方式编码到字节串或从字节串解码,形成格式良好的编码数据项。编码在附录 B 的表7中进行了总结,按初始字节索引。编码器必须 (MUST) 只生成格式良好的编码数据项。解码器在遇到不是格式良好的 CBOR 数据项的输入时,必须不 (MUST NOT) 返回已解码的数据项 (这并不妨碍诊断和恢复工具从损坏的编码 CBOR 数据项中提供一些信息的用处)。

每个编码数据项的初始字节包含关于主类型 (高3位,在第 3.1 节中描述) 和附加信息 (低5位) 的信息。除了少数例外,附加信息的值描述了如何加载一个无符号整数"参数":

  • 小于24: 参数的值就是附加信息的值。
  • 24、25、26或27: 参数的值分别保存在接下来的 1、2、4 或 8 个字节中,采用网络字节序。对于主类型7和附加信息值 25、26、27,这些字节不用作整数参数,而是用作浮点值 (参见第 3.3 节)。
  • 28、29、30: 这些值保留供将来添加到 CBOR 格式。在当前版本的 CBOR 中,编码项是不格式良好的。
  • 31: 不派生参数值。如果主类型是 0、1 或 6,则编码项不格式良好。对于主类型 2 到 5,项的长度是不定长的,对于主类型 7,该字节根本不构成数据项,而是终止不定长项;所有这些都在第 3.2 节中描述。

初始字节和用于构造参数的任何附加字节统称为数据项的头部 (head)。

此参数的含义取决于主类型。例如,在主类型 0 中,参数就是数据项本身的值 (在主类型 1 中,数据项的值是从参数计算出来的);在主类型 2 和 3 中,它给出后续字节串数据的长度 (以字节为单位);在主类型 4 和 5 中,它用于确定所包含的数据项数量。

如果编码的字节序列在数据项结束之前结束,则该项不格式良好。如果在最外层编码项解码之后编码的字节序列仍有剩余字节,则该编码不是单个格式良好的 CBOR 项。根据应用程序的不同,解码器可以将编码视为不格式良好,或者只是向应用程序标识剩余字节的开始位置。

CBOR 解码器实现可以基于一个跳转表,该表包含初始字节的所有 256 个定义值 (表7)。受限实现中的解码器可以改为使用初始字节和后续字节的结构来获得更紧凑的代码 (有关这可能是什么样子的粗略印象,请参见附录 C)。

3.1. 主类型 (Major Types)

以下列出了主类型以及与类型相关的附加信息和其他字节。

  • 主类型0: 范围 0..2^64-1 (含) 内的无符号整数。编码项的值就是参数本身。例如,整数 10 表示为单字节 0b000_01010 (主类型 0,附加信息 10)。整数 500 将是 0b000_11001 (主类型 0,附加信息 25),后跟两个字节 0x01f4,即十进制的 500。

  • 主类型1: 范围 -2^64..-1 (含) 内的负整数。项的值是 -1 减去参数。例如,整数 -500 将是 0b001_11001 (主类型 1,附加信息 25),后跟两个字节 0x01f3,即十进制的 499。

  • 主类型2: 字节串 (byte string)。串中的字节数等于参数。例如,长度为 5 的字节串将具有初始字节 0b010_00101 (主类型 2,长度的附加信息 5),后跟 5 个字节的二进制内容。长度为 500 的字节串将具有 3 个初始字节 0b010_11001 (主类型 2,附加信息 25 表示双字节长度),后跟两个字节 0x01f4 表示长度 500,再后跟 500 个字节的二进制内容。

  • 主类型3: 以 UTF-8 [RFC3629] 编码的文本串 (text string) (第2节)。串中的字节数等于参数。包含无效 UTF-8 序列的串是格式良好的但无效的 (第 1.2 节)。提供此类型是为了需要解释或显示人类可读文本的系统,并允许区分非结构化字节和具有指定字符集 (Unicode) 和编码 (UTF-8) 的文本。与 JSON 等格式不同,此类型中的 Unicode 字符永远不会转义。因此,换行符 (U+000A) 在串中始终表示为字节 0x0a,永远不会表示为字节 0x5c6e (字符""和"n"),也不会表示为 0x5c7530303061 (字符""、"u"、"0"、"0"、"0"和"a")。

  • 主类型4: 数据项的数组 (array)。在其他格式中,数组也称为列表、序列或元组 ("CBOR 序列"是略有不同的东西,尽管 [RFC8742])。参数是数组中数据项的数量。数组中的项不需要都是同一类型。例如,包含任何类型的 10 个项的数组将具有初始字节 0b100_01010 (主类型 4,长度的附加信息 10),后跟 10 个剩余项。

  • 主类型5: 数据项对的映射 (map)。映射也称为表、字典、哈希或对象 (在 JSON 中)。映射由数据项对组成,每对由一个键组成,该键后面紧跟一个值。参数是映射中数据项对的数量。例如,包含 9 对的映射将具有初始字节 0b101_01001 (主类型 5,对数的附加信息 9),后跟 18 个剩余项。第一项是第一个键,第二项是第一个值,第三项是第二个键,依此类推。因为映射中的项成对出现,所以它们的总数始终是偶数:包含奇数项 (最后一个键数据项之后没有值数据) 的映射不格式良好。具有重复键的映射可能是格式良好的,但它无效,因此会导致不确定的解码;另请参见第 5.6 节。

  • 主类型6: 标记的数据项 ("tag"),其标记号 (范围 0..2^64-1 (含) 内的整数) 是参数,其包含的数据项 (标记内容) 是头部之后的单个编码数据项。参见第 3.4 节。

  • 主类型7: 浮点数和简单值,以及"break"停止码。参见第 3.3 节。

这八个主类型产生一个简单的表,显示数据项初始字节的 256 个可能值中哪些被使用 (表7)。

在主类型 6 和 7 中,许多可能的值保留供将来规范使用。有关这些值的更多信息,请参见第 9 节。

表1总结了 CBOR 定义的主类型,暂时忽略第 3.2 节。此表中的数字 N 代表参数。

表1: CBOR 主类型的定长使用概述 (N = 参数)

主类型含义内容
0无符号整数 N-
1负整数 -1-N-
2字节串N 字节
3文本串N 字节 (UTF-8 文本)
4数组N 个数据项 (元素)
5映射2N 个数据项 (键/值对)
6编号为 N 的标记1 个数据项
7简单值/浮点-

3.2. 某些主类型的不定长 (Indefinite Lengths for Some Major Types)

四个 CBOR 项 (数组、映射、字节串和文本串) 可以使用附加信息值 31 以不定长编码。如果在知道数组或映射内的项数或串的总长度之前需要开始对项进行编码,这将很有用。(在该数据项内的所有数据已知之前就能够开始发送数据项的能力通常被称为在该数据项内"流式传输"。)

不定长数组和映射的处理方式与不定长串 (字节串和文本串) 不同。

3.2.1. "break" 停止码 (The "break" Stop Code)

"break" 停止码使用主类型 7 和附加信息值 31 (0b111_11111) 进行编码。它本身不是数据项:它只是用于关闭不定长项的语法特性。

如果"break"停止码出现在期望数据项的位置,而不是直接在不定长串、数组或映射内 —— 例如,直接在定长数组或映射内 —— 则包含项不格式良好。

3.2.2. 不定长数组和映射 (Indefinite-Length Arrays and Maps)

不定长数组和映射使用其主类型表示,附加信息值为 31,后跟对于数组为零个或多个项的任意长度序列或对于映射为键/值对的任意长度序列,然后是"break"停止码 (第 3.2.1 节)。换句话说,不定长数组和映射看起来与其他数组和映射相同,除了以附加信息值 31 开始并以"break"停止码结束。

如果"break"停止码在映射中的键之后出现,代替该键的值,则映射不格式良好。

对嵌套不定长数组或映射项没有限制。"break"仅终止单个项,因此嵌套的不定长项需要与开始不定长项的类型字节一样多的"break"停止码。

3.2.3. 不定长字节串和文本串 (Indefinite-Length Byte Strings and Text Strings)

不定长串由包含字节串或文本串的主类型且附加信息值为 31 的字节表示,后跟零个或多个具有定长的指定类型的串 ("块"),并由"break"停止码 (第 3.2.1 节) 结束。不定长串表示的数据项是块的连接。如果不存在块,则数据项是指定类型的空串。允许零长度块,尽管不是特别有用。

如果不定长串指示符 (0b010_11111 或 0b011_11111) 和"break"停止码之间的任何项不是相同主类型的定长串项,则该串不格式良好。

该设计不允许将不定长串作为块嵌套到不定长串中。如果允许,它将要求解码器实现保持堆栈或至少嵌套级别的计数。这在编码器端是不必要的,因为内部不定长串将由块组成,而这些块可以直接放入外部不定长串中。

如果不定长文本串内的任何定长文本串无效,则该不定长文本串无效。请注意,这意味着单个 Unicode 码点 (标量值) 的 UTF-8 字节不能分散在块之间:文本串的新块只能在码点边界开始。

3.2.4. 主类型不定长使用总结 (Summary of Indefinite-Length Use of Major Types)

表2总结了 CBOR 定义的用于不定长编码的主类型 (附加信息设置为 31)。

表2: CBOR 主类型的不定长使用概述 (附加信息 = 31)

主类型含义包含到"break"停止码
0(不格式良好)-
1(不格式良好)-
2字节串定长字节串
3文本串定长文本串
4数组数据项 (元素)
5映射数据项 (键/值对)
6(不格式良好)-
7"break" 停止码-

3.3. 浮点数和无内容值 (Floating-Point Numbers and Values with No Content)

主类型 7 用于两种类型的数据:浮点数和不需要任何内容的"简单值"。初始字节中 5 位附加信息的每个值都有其自己的独立含义,如表3所定义。与整数的主类型一样,此主类型的项不携带内容数据;所有信息都在初始字节 (头部) 中。

表3: 主类型7中附加信息的值

5 位值语义
0..23简单值 (值 0..23)
24简单值 (值 32..255 在后续字节中)
25IEEE 754 半精度浮点 (后跟 16 位)
26IEEE 754 单精度浮点 (后跟 32 位)
27IEEE 754 双精度浮点 (后跟 64 位)
28-30保留,在本文档中不格式良好
31用于不定长项的"break"停止码 (第 3.2.1 节)

与所有其他主类型一样,5 位值 24 表示单字节扩展:后跟一个附加字节来表示简单值。(为了最大程度地减少混淆,仅使用值 32 到 255。) 这保持了初始字节的结构:对于其他主类型,这些的长度始终取决于第一个字节中的附加信息。表4列出了分配给简单值和可用的数值。

表4: 简单值

语义
0..19(未分配)
20false
21true
22null
23undefined
24..31(保留)
32..255(未分配)

编码器必须不 (MUST NOT) 发出以 0xf8 (主类型 7,附加信息 24) 开头并继续以小于 0x20 (十进制 32) 的字节的双字节序列。此类序列不格式良好。(这意味着编码器不能以双字节序列编码 falsetruenullundefined,并且只有这些的单字节变体是格式良好的;更一般地说,每个简单值只有一个表示变体。)

5 位值 25、26 和 27 用于 16 位、32 位和 64 位 IEEE 754 二进制浮点值 [IEEE754]。这些浮点值在适当大小的附加字节中编码。(有关 16 位浮点数的一些信息,请参见附录 D。)


相关链接: