跳到主要内容

3. Presentation Language (表示语言)

本文档处理数据在外部表示中的格式. 以下使用一种非常基础且相对宽松定义的表示语法.

3.1 Basic Block Size (基本块大小)​

所有数据项的表示都被显式规定. 基本数据块大小为一个 byte, 即 8 bit. 多 byte 数据项是按从左到右, 从上到下顺序串接的 byte. 从 byte stream 中形成一个多 byte 项时, 例如下面的数字, 使用类似 C 的记法:

value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |
... | byte[n-1];

这种多 byte 值的 byte ordering 是常见的 network byte order, 即 big-endian format.

3.2 Miscellaneous (杂项)​

comment 以 /* 开始, 以 */ 结束.

optional component 用 [[ ]] (双中括号) 包围表示.

包含未解释数据的单 byte entity 类型为 opaque.

已有类型 T 的 type alias T' 通过如下方式定义:

T T';

3.3 Numbers (数字)​

基本 numeric data type 是 unsigned byte (uint8). 所有更大的 numeric data type 都由固定长度 byte 序列按第 3.1 节描述串接形成, 并且也是 unsigned. 预定义 numeric type 如下:

uint8 uint16[2];
uint8 uint24[3];
uint8 uint32[4];
uint8 uint64[8];

本规范中所有值均以 network byte (big-endian) order 传输. 由十六进制 byte 01 02 03 04 表示的 uint32 等价于十进制值 16909060.

3.4 Vectors (向量)​

vector (一维数组) 是同质数据元素流. vector 大小可以在文档编写时指定, 也可以留到运行时指定. 无论哪种情况, length 声明的是 vector 中的 byte 数, 而不是元素数. 固定长度 vector 类型 T' 的语法如下:

T T'[n];

这里 T' 在数据流中占用 n byte, 其中 n 是 T 大小的倍数. vector length 不包含在编码流中.

例如, Datum 定义为三个连续且协议不解释的 byte, Data 定义为三个连续的 Datum, 总共消耗九个 byte.

opaque Datum[3];      /* three uninterpreted bytes */
Datum Data[9]; /* three consecutive 3-byte vectors */

variable-length vector 通过 &lt;floor..ceiling> 记法指定合法 length 子范围, 包含端点. 编码时, 实际 length 位于 vector 内容之前. length 字段会使用足够 byte 来表示指定最大值 ceiling. 实际 length 字段为零的 variable-length vector 称为空 vector.

T T'&lt;floor..ceiling>;

例如, mandatory 是必须包含 300 到 400 byte 的 opaque vector, 不可能为空. 其实际 length 字段消耗两个 byte, 即 uint16, 足以表示 400. 同理, longer 可表示最多 800 byte 数据或 400 个 uint16 元素, 并且可以为空. 其编码会在 vector 前带一个两 byte 的实际 length 字段. 编码后 vector 的 length 必须是单个元素 length 的整数倍, 例如 17 byte 的 uint16 vector 是非法的.

opaque mandatory&lt;300..400>;
/* length field is two bytes, cannot be empty */
uint16 longer&lt;0..800>;
/* zero to 400 16-bit unsigned integers */

3.5 Enumerateds (枚举)​

额外的稀疏数据类型称为 enum. 每个定义都是不同类型. 只有同一类型的 enumerated 才能赋值或比较. 每个 enumerated 元素都必须分配一个值. 由于 enumerated 元素无序, 它们可以按任意顺序分配任意唯一值.

enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;

未来的协议扩展或新增内容可以定义新值. 除非字段定义另有说明, 实现需要能够解析并忽略未知值.

enumerated 在 byte stream 中占用的空间与其最大已定义 ordinal value 所需空间相同. 以下定义会使 Color 类型字段占用一个 byte:

enum { red(3), blue(5), white(7) } Color;

也可以选择指定一个没有关联 tag 的值, 以强制 width definition 而不定义多余元素.

enum { sweet(1), sour(2), bitter(4), (32000) } Taste;

enumeration 元素名称作用域限定在所定义类型内. 如果赋值目标明确, 可以不使用完整限定名.

Color color = Color.blue;     /* overspecified, legal */
Color color = blue; /* correct, type implicit */

元素名称不要求唯一, 但元素的数值必须唯一.

enum { low(1), medium(2), high(2) } Priority;  /* WRONG */

对从不转换为外部表示的 enumerated, 可以省略数值信息.

enum { low, medium, high } Priority;

3.6 Constructed Types (构造类型)​

structure type 可由 primitive type 构造以便使用. 每个 specification 都声明一个新的唯一类型. 定义语法类似 C:

struct {
T1 f1;
T2 f2;
...
Tn fn;
} T;

fixed-length 和 variable-length vector field 都允许使用标准 vector 语法. Section 3.8 的 variant 示例展示了这一点.

structure 内的 field 可以使用类型名称限定, 语法类似 enumerated. 例如, T.f2 指前述声明中的第二个 field.

3.7 Constants (常量)​

field 和 variable 可以使用 = 分配固定值:

struct {
T1 f1 = 8; /* T.f1 must always be 8 */
T2 f2;
} T;

3.8 Variants (变体)​

已定义 structure 可以基于运行环境中可用的某些信息具有 variant. selector 必须是定义了该 structure 可能 variant 的 enumerated type. variant structure 的每个 arm 指定该 variant field 的类型和可选 field label. presentation language 不规定运行时选择 variant 的机制.

struct {
T1 f1;
T2 f2;
....
Tn fn;
select (E) {
case e1: Te1 [[fe1]];
case e2: Te2 [[fe2]];
....
case en: Ten [[fen]];
};
} Tv;

示例:

enum { apple, orange, banana } VariantTag;

struct {
uint16 number;
opaque string&lt;0..10>; /* variable length */
} V1;

struct {
uint32 number;
opaque string[10]; /* fixed length */
} V2;

struct {
VariantTag type;
select (VariantRecord.type) {
case apple: V1;
case orange:
case banana: V2;
};
} VariantRecord;