跳到主要内容

2. 类型化数组 (Typed Arrays)

2. 类型化数组 (Typed Arrays)

类型化数组是由数字组成的同构数组, 其中所有数字都以单一二进制表示形式编码. 这些表示形式的串接被编码为单个 CBOR 字节字符串 (major type 2), 并由单个标签包围, 该标签指示字节字符串中表示的所有数字的类型和编码.

2.1 数字类型

这里关注三类数字: 无符号整数 (uint)、有符号整数 (二进制补码, sint), 以及 IEEE 754 二进制浮点数 (始终为有符号). 对于每一类, 当前都有多种表示长度在使用:

             +-----------+--------+--------+-----------+
| Length ll | uint | sint | float |
+===========+========+========+===========+
| 0 | uint8 | sint8 | binary16 |
+-----------+--------+--------+-----------+
| 1 | uint16 | sint16 | binary32 |
+-----------+--------+--------+-----------+
| 2 | uint32 | sint32 | binary64 |
+-----------+--------+--------+-----------+
| 3 | uint64 | sint64 | binary128 |
+-----------+--------+--------+-----------+

Table 1: Length Values

这里, sintN 表示精确 N 位的有符号整数 (例如 sint16), uintN 表示精确 N 位的无符号整数 (例如 uint32). 名称 binaryN 表示 IEEE 754 [IEEE754] 中定义的同名数字形式.

由于这些标签的目标之一是能够直接传送类型化数组底层的 ArrayBuffer 而无需重新编码, 而这些 ArrayBuffer 可能采用大端 (网络字节序) 或小端形式, 因此需要为两种变体都定义标签.

这总共会产生 24 种变体. 在标签中, 需要表达整数与浮点的选择、符号性 (对于整数)、字节序, 以及四种长度值之一.

为简化实现, 分配了一段标签范围, 允许从标签位中取回所有这些信息: 标签值 64 到 87.

该值被拆分为 5 个位字段: 0b010, f, s, e 和 ll, 详见表 2.

  +-------+-------------------------------------------------------+
| Field | Use |
+=======+=======================================================+
| 0b010 | the constant bits 0, 1, 0 |
+-------+-------------------------------------------------------+
| f | 0 for integer, 1 for float |
+-------+-------------------------------------------------------+
| s | 0 for float or unsigned integer, 1 for signed integer |
+-------+-------------------------------------------------------+
| e | 0 for big endian, 1 for little endian |
+-------+-------------------------------------------------------+
| ll | A number for the length (Table 1). |
+-------+-------------------------------------------------------+

Table 2: Bit Fields in the Low 8 Bits of the Tag

随后, 每个数组元素中的字节数可通过 "2**(f + ll)" 计算 (在典型编程语言中为 "1 << (f + ll)"). 注意, 0f 和 ll 分别是该字节中每个 4 位半字节的两个最低有效位.

在 CBOR 表示中, 数组中的元素总数不会显式表达, 而是由字节字符串长度和每个表示的长度隐含给出. 可通过对前述公式取逆, 根据构成数组表示的字节字符串长度 (单位为字节) 计算: "bytelength >> (f + ll)".

对于 uint8/sint8 值, 字节序是冗余的. 只使用并分配大端变体的标签. 表示 sint8 小端变体的标签 MUST NOT 使用; 其标签号标记为预留. 作为特殊情况, 原本表示 uint8 小端变体的标签被改为表示数组中的数字使用来自整数的钳制转换, 如 ES10 JavaScript 规范 ("ToUint8Clamp") [ECMA-ES10] 第 7.1.11 节 (http://www.ecma-international.org/ecma-262/6.0/#sec-touint8clamp) 中更详细描述; 这里的假设是, 解码后该数组的程序内部表示会以这种方式标记, 以便进一步处理, 从而通过 CBOR 提供 JavaScript 类型化数组的"往返"能力.

IEEE 754 二进制浮点数始终为有符号. 因此, 对于 float 变体 ("f" == 1), 不需要区分有符号和无符号变体; "s" 位始终为零. "s" 为一时对应的标签号 (即标签值 88 到 95) 仍可由其他规范自由使用.