RFC-0022:說明:結構成員的預設值

RFC-0022:澄清說明:結構體成員的預設值
狀態已接受
領域
  • FIDL
說明

FIDL 結構成員可能有預設值。目前,我們僅部分導入預設值 (見下文),因此本提案旨在闡明預設行為的預期行為。

作者
提交日期 (年-月-日)2018-07-17
審查日期 (年-月-日)2018-09-27

摘要

FIDL 結構成員可能有預設值。 今天,系統已部分實作預設值 (請見下方章節)。 本提案旨在清楚說明預設值的行為。

提振精神

  1. 提供跨語言繫結的規律性,提供保護措施 避免不一致或非預期的使用情形
  2. 避免在成員花費太多時間的情況下手動初始化 語言需要明確初始化

其中包括:

  • 減少傳輸格式的位元組

並「不是」鼓勵透過傳輸格式節省位元組或節省處理資料 編碼或解碼效果提升

現行的實作方式

預設值可在結構體成員上的 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,當中清楚說明瞭預設值的語意。 以及繫結的需求條件

支援的類型

  • 原始類型:
    • boolint8int16int32int64uint8uint16uint32uint64float32float64
  • 不可為空值的 stringstring:N
    • string:N 應將預留且未使用的記憶體歸零。

不支援的類型

  • array<T>:N
    • 設為 0
  • 不可為空值的類型:vector<T>vector<T>:N
    • 設為 0
  • 可為空值類型:string?string:N?vector<T>?vector<T>:N?
    • 設為空值
  • 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 概念 零值,其中宣告的變數在沒有明確初始值的情況下 初始化為 0

開放原始碼做法:

// 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
}