跳到主要内容

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;