RFC-0025:Bit flag

RFC-0025:位标志
状态已接受
区域
  • FIDL
说明

使用位标志声明扩展 FIDL 语言。

作者
提交日期(年-月-日)2019-01-14
审核日期(年-月-日)2019-01-24

“Just a Little Bit”

摘要

使用位标志声明扩展 FIDL 语言。

设计初衷

在 FDL 中,有几种使用场景可用于描述整数的一组标志。目前,建议 FIDL 用户创建一组具有相同底层类型的常量。由于这些都是独立的,因此绑定无法在运行时检测到无效值的创建。

设计

来源语言更改

此提案将 bits 关键字添加到 FIDL。

bits 引入了类似于 enum 的顶级声明。形式上,该语法中的生成式如下所示:

bits-declaration = ( attribute-list ) , "bits" , IDENTIFIER , ( ":" , type-constructor ) ,
                   "{" , ( bits-or-enum-member , ";" )+ , "}" ; [NOTE 1]

bits-or-enum-member = ( attribute-list ) , IDENTIFIER , ( "=" , bits-or-enum-member-value ) ;

bits-or-enum-member-value = IDENTIFIER | literal ; [NOTE 2]

注意:

  1. bits-declaration 允许在语法中使用更宽松的 type-constructor,但编译器将其限制为无符号整数类型,请参阅基元

  2. bits-or-enum-member-value 允许在语法中使用更宽松的 literal,但编译器将其限制为:

    • enum 上下文中的 NUMERIC-LITERAL
    • bits 上下文中的 NUMERIC-LITERAL,必须为二的幂。

bits 声明中的每个成员都是二的幂。为简单起见,此提案建议不允许在 bits 声明本身中使用更复杂的表达式,也不允许在 bits 常量表达式中对这些表达式进行 OR 运算。这些属性日后可能会添加到 bits 声明中。

bits 声明示例,摘自 fuchsia.io 库中当前的常量:

bits OpenRights : uint32 {
    READABLE = 0x00000001;
    WRITABLE = 0x00000002;
    ADMIN = 0x00000004;
};

此外,此提案还添加了二进制字面量语法,如下所示:

bits OpenRights : uint32 {
    READABLE = 0b0001;
    WRITABLE = 0b0010;
    ADMIN = 0b0100;
};

语义

溢出底层整数类型是编译错误。

每个 bits 成员值都必须是不同的。

使用不是 bits 声明成员的位集对 bits 值进行序列化或反序列化会导致验证错误。

bits 的语义与 enum 不同。enum 值必须是 FIDL 中声明的值之一,而 bits 则不一定。例如,如果 OpenRightsenum,则可发送的唯一有效值为 124。不过,作为 bits 类型,03567 也都是有效值。

绑定

每个语言绑定都将扩展,以便以惯用方式处理这些值。在最糟糕的情况下,这只会为每个 bits 成员生成一个常量,就像它是底层类型的整数常量一样。

bits 值的线格格式与底层整数值相同。

序列化和反序列化代码应确保该值是所述位的一小部分。例如,尝试将 8 用作 OpenRights 值应会失败验证。

信号和权限常量

我还建议向 zx 库添加信号和正确的处理程序值。 这包括所有信号值和权限的 bits 声明,以及可能包含每种句柄类型的默认权限的一组常量。

实施策略

第 1 阶段

将所有源代码更改添加到 FIDL 编译器,包括解析器测试。

第 2 阶段

为所有语言绑定和兼容性测试套件添加了支持。

第 3 阶段

将现有的 int 常量堆迁移到 bits

工效学设计

这项变更让用户可以明确表达其意图,读者可以看到明确的分组,从而使 FIDL 更加符合人体工学。

文档和示例

此提案介绍了对上述 FIDL 语法所做的更改。

我会调整 FIDL 教程,在其中添加此模式的示例。

向后兼容性

这是对 FIDL 源代码的向后兼容更改。

线格格式向后兼容,这意味着无论以 uint32 还是 bits Bits : uint32 的形式发送,(2 | 4)6 的值在线路上都是相同的。

性能

将 FIDL 中的类型从 uint32 更改为 bits 值会在检查序列化或反序列化值是否有效的绑定中增加一些小开销。

这是位掩码和分支,不太可能被注意到。

安全

我认为这不会带来安全问题。 更好的类型安全性可能是一项小优势。

测试

fidlc 主机单元测试将运行 FIDL 解析器。

兼容性测试套件将扩展为包含各种大小和值的 bits 类型,以演练所有受支持绑定的发送和接收路径。

缺点、替代方案和未知情况

此提案建议仅允许对无符号整数类型使用位。我认为可以允许对已签名的底层类型执行此操作,但在所有语言绑定中,需要比理想情况更谨慎。我更希望我们不要在 C/C++ 中意外地将位移得太远。

更通用的位字段模式似乎比此提案更复杂。我的意思是将整数类型划分为几个位范围,并为每个位范围指定一个字段名称。

&~ 表达式似乎没有必要,至少在开始时是这样。目标语言可以选择支持对位标志值执行此类算术表达式,但我目前还没有看到直接在 FIDL 常量中使用它们的必要性。

在先技术和参考文档

人们不愿对成员值执行过于复杂的操作,并避免使用有符号类型,是因为他们对 C 和 C++ 中的这些概念一直存在混淆,而这些绑定必须支持此概念。