FIDL 词典

本文档定义了在 FIDL 上下文中具有特定含义的一般术语。如需详细了解具体的 FIDL 主题,请参阅 FIDL 标头

类型、布局、约束条件

类型用于对 FIDL 类型系统中的值进行分类。类型显示在 FIDL 语法中定义的 type-constructor 位置。例如,uint32string:10vector<bool> 是类型。

布局是类型的可参数化描述。它并不是指一种类型,而是描述通过使用零个或多个布局参数实例化布局来获取的一系列类型。例如,vector 是一个布局,它接受一个布局参数,这种类型(例如 vector<bool> 本身)就是一个类型。再举一个例子,array 是一个布局,它接受两个布局参数,从而生成 array<bool, 3> 等类型。

布局和类型之间的区别可能微乎其微。例如,上面的 uint32 是一种类型并不严格。相反,它是一种不需要任何参数的布局,与实例化获得的类型不同。 FIDL 语法不会捕获这种区别,因此,当在类型位置(例如 alias uint = uint32;)中使用 uint32 时,它实际上会引用布局 uint32,并使用零布局参数将其隐式实例化。

限制条件将类型限制为仅允许满足谓词的值。例如,类型 string:10 具有约束条件 length <= 10(缩写为 10),这意味着字符串长度不能超过 10 个字节。

布局和布局参数会影响字节在 FIDL 传输格式中的布局方式,而约束条件会影响对可以表示的内容进行限制的验证(如需了解详情,请参阅 RFC-050)。 从语法上讲,布局参数只能应用于布局,约束条件只能应用于类型。例如:

alias Bools = vector<bool>;       // ok: layout parameter applied to layout
alias MaxTenBools = Bools:10;     // ok: constraint applied to type
alias MaxTenBytes = Bools<byte>;  // INVALID: layout parameter applied to type
alias MaxTen = vector:10;         // INVALID: constraint applied to layout

类型实例化的一般形式是

L<L_1, L_2, ..., L_n>:<C_1, C_2, ..., C_n>

其中,L 是布局,L_1L_n 是布局参数,C_1C_n 是约束条件。

成员、字段、变体

声明的成员是属于声明的单个元素,即声明由 0 个、1 个或多个成员组成。

例如,假设存在 Mode 位声明:

type Mode = strict bits {
    READ = 1;
    WRITE = 2;
};

READWRITE 都是成员。

在引用结构体或表的成员时,我们可以更具体地将这些成员称为字段。

在引用联合的成员时,我们可以更具体地将这些成员称为变体。

例如,假设存在 Command 联合声明:

type Command = strict union {
    1: create_resource CreateResource;
    2: release_resource ReleaseResource;
};

两个变体是 create_resourcerelease_resource

此外,并集实例的选定变体是该联合体当时持有的当前值。

标记和序数

标记是目标语言变体判别器,即目标语言中用于表示并集的选定变体的特定结构。例如,请考虑以下 Command 联合的 TypeScript 表示法:

enum CommandTag {
    Create,
    Release,
}

interface Command {
    tag: CommandTag,
    data: CreateResource | ReleaseResource,
}

Command 的标记为 Command.tag,类型为 CommandTag。表示 Command 的每个变体的实际值和类型取决于实现。

请注意,某些语言不需要标记。例如,某些语言会使用模式匹配在联合的变体上分支,而不是使用显式标记值。

序数是线上变体判别器,即用于表示 FIDL 有线格式中并集的变体的值。序数在 FIDL 定义中明确指定(在此示例中,1 表示 create_resource,2 表示 release_resource)。

编码

编码是指将值从目标语言序列化为 FIDL 传输格式的过程。

对于 C 绑定系列(HLCPP、 LLCPP),编码可能具有更具体的含义,即获取与 FIDL 有线格式的布局匹配的字节,并通过将指针和句柄替换为 FIDL_ALLOC_PRESENT/FIDL_ALLOC_ABSENTFIDL_HANDLE_PRESENT/FIDL_HANDLE_ABSENT,将句柄移动到带外句柄表中。

解码

解码是指将 FIDL 传输格式的原始字节中的值反序列化为目标语言的值的过程。

对于 C 绑定系列(HLCPP、 LLCPP),解码可能具有更具体的含义,即获取与 FIDL 传输格式的布局匹配的字节,并通过将 FIDL_ALLOC_PRESENT/FIDL_ALLOC_ABSENTFIDL_HANDLE_PRESENT/FIDL_HANDLE_ABSENT 替换为“实际”指针/句柄值来修补指针和句柄,从而将句柄移出带外句柄表。

验证

验证是检查给定值是否满足 FIDL 定义中的限制条件的过程。在发送值之前对值进行编码时,或在接收值后对值进行解码时,都会进行验证。约束条件示例包括矢量边界、句柄约束和字符串的有效编码为 UTF-8。

验证失败时,绑定会通过直接返回或通过错误回调将错误显示给用户代码。

结果/错误类型

对于指定了错误类型的方法:

DoWork() -> (struct { result Data; }) error uint32

“结果类型”是指服务器针对此方法接收的整条消息,即由 Data 结果或 uint32 错误组成的并集。在这种情况下,错误类型为 uint32,而 Data 可以是响应类型,也可以是成功类型。