RFC-0022:说明:结构体成员的默认值 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | FIDL 结构体成员可以具有默认值。目前,对默认设置的支持已部分实现(请参见下一部分),该方案旨在阐明默认设置的行为方式。 |
作者 | |
提交日期(年-月-日) | 2018-07-17 |
审核日期(年-月-日) | 2018-09-27 |
摘要
FIDL 结构体成员可以具有默认值。 目前,对默认值的支持已部分实现(请参阅下文), 该方案旨在阐明默认设置的行为方式。
设计初衷
- 它可以确保语言绑定的规律性, 使用方式不一致或意外使用
- 避免了手动进行逐个成员初始化的麻烦, 而语言需要显式初始化,
非动机包括:
- 以传输格式保存字节
这不是为了节省传输格式的字节或节省处理工作的动机 编码或解码。
今天的实现
默认值可以在结构体成员上以 FIDL 语言表达:
- (+) 支持数字字面量、布尔值字面量和字符串 字面量。
- (-)
fidlc
不提供对字面量赋予 结构体成员。 可以使用字符串字面量“hello”指定布尔值 为 uint 分配的负数,或分配的出界数字 转换为 int16。 - (-) 语言绑定支持不一致,目前仅适用于 C++ 和 Dart 绑定。 不支持 Go、C 或 Rust。
例如(来自 //zircon/system/host/fidl/examples/types.test.fidl):
struct default_values {
bool b1 = true;
bool b2 = false;
int8 i8 = -23;
int16 i16 = 34;
int32 i32 = -34595;
int64 i64 = 3948038;
uint8 u8 = 0;
uint16 u16 = 348;
uint32 u32 = 9038;
uint64 u64 = 19835;
float32 f32 = 1.30;
float64 f64 = 0.0000054;
string s = "hello";
};
设计
可以在结构体成员中定义默认值。
默认值显示在字段定义的末尾,采用类似 C 的 = {value}
模式。
语法
// cat.fidl
enum CatAction : int8 {
SIT = -10;
WALK = 0;
SNEAK = 2;
};
struct Location {
uint8 pos_x = 10; // Position X
uint8 pos_y; // Position Y. Default unspecified. Fall-back to 0
float32 pos_z = 3.14; // Position Z.
float32 pos_t; // Default unspecified. Fall-back to 0.0
};
struct Cat {
string name; // Automatic default to empty string
CatAction action = CatAction::SNEAK;
Location loc;
};
语义
请参阅 RFC-006,其中阐明了默认值的语义, 有关绑定的要求和要求
支持的类型
- 基元类型:
<ph type="x-smartling-placeholder">
- </ph>
bool
、int8
、int16
、int32
、int64
、uint8
、uint16
、uint32
uint64
、float32
、float64
string
、string:N
不可为 null <ph type="x-smartling-placeholder">- </ph>
string:N
应将预留而未使用的内存清零。
不支持的类型
array<T>:N
- 设置为零
- 不可为 null 的类型:
vector<T>
、vector<T>:N
<ph type="x-smartling-placeholder">- </ph>
- 设置为零
- 可为 null 的类型:
string?
、string:N?
、vector<T>?
、vector<T>:N?
- 设为 null
handle
struct
- 虽然
struct
中的每位成员都可以有一个默认值,struct
本身没有默认值。
- 虽然
union
- 为避免冲突,
union
成员的任何默认值 或union
的子结构(任何深度)的布局应设为 已忽略。
- 为避免冲突,
默认值的细微差别
关注点是值本身,而不是分配方式 值。 这至少意味着两件事:
- 没有区别 - 如果由于参数 是否已被其他机制明确分配。
- 在 进行编组或解组的时间
实现
以下是一些针对 C、Rust 和 Go 绑定的实现创意示例
// in FIDL "default.fidl"
struct Location {
uint8 pos_x = 10;
uint8 pos_y = 20;
uint8 pos_x; // Should be set to "zero" according to above.
};
// C binding "defaults/fidl.h"
typedef struct _Location_raw {
uint8_t pos_x;
uint8_t pos_y;
uint8_t pos_z
} Location;
Location Location_default = { 10, 20, 0 }; // Or in the source file.
// May be used for memcmp,
memcpy, etc.
#define Location(my_instance) Location my_instance = Location_default;
// C code "example.c"
#include <fidl.h>
void showme(Location loc) {
printf("(%u, %u, %u)\n", loc.pos_x, loc.pos_y, loc.pos_z);
}
int main() {
Location(alpha);
Location beta;
Location gamma = Location_default;
showme(alpha); showme(beta); showme(gamma);
return 0;
}
// Rust binding
struct Location {
pos_x: u8,
pos_y: u8,
pos_z: u8,
}
impl std::default::Default for Location {
fn default() -> Self { Self { pos_x: 10, pos_y: 20, pos_z: 0 } }
}
// Go binding, using export control
type location struct {
pos_x uint8
pos_y uint8
pos_z uint8
}
Func NewLocation() location {
loc := location{}
loc.pos_x = 10
loc.pos_y = 20
// loc.pos_z = 0 Maybe omitted.
return loc
}
性能
不适用
安全
不适用
测试
不适用
向后兼容性
此更改会使 FIDL 文件源向后兼容。无 ABI 或 需要更改传输格式。
缺点、替代方案和未知问题
如果在所有语言绑定中实现此方法会 简单明了。
先验技术和参考资料
协议缓冲区,平面缓冲区提供默认值。Golang 有一个概念 零值值,其中声明的变量没有明确的初始值 明确初始化为零。
开源方法:
// From https://github.com/creasty/defaults
type Sample struct {
Name string `default:"John Smith"`
Age int `default:"27"`
Gender Gender `default:"m"`
Slice []string `default:"[]"`
SliceByJSON []int `default:"[1, 2, 3]"` // Supports JSON format
Map map[string]int `default:"{}"`
MapByJSON map[string]int `default:"{\"foo\": 123}"`
Struct OtherStruct `default:"{}"`
StructPtr *OtherStruct `default:"{\"Foo\": 123}"`
NoTag OtherStruct // Recurses into a nested struct even without a tag
OptOut OtherStruct `default:"-"` // Opt-out
}