RFC-0040:識別碼唯一性

RFC-0040:識別碼唯一性
狀態已接受
區域
  • FIDL
說明

FIDL 規格和前端編譯器目前會根據簡單的字串比較結果,考慮到兩個不同的 ID。這提出了新的演算法,可將繫結產生器的轉換作業納入考量。

作者
提交日期 (年/月)2019-04-08
審查日期 (年/月)2019-05-14

「SnowFlake 對 SNOW_FLAKE」

摘要

FIDL 規格和前端編譯器目前會根據簡單的字串比較,將兩個 ID 視為不同的 ID。 這提供新的演算法,可將繫結產生器進行的轉換作業納入考量。

提振精神

語言繫結產生器會轉換 ID,以符合譯文語言限制和樣式,將多個 FIDL ID 對應至單一指定語言 ID。這可能會導致在指定特定語言之前,無法顯示非預期的衝突。

設計

這項做法提議針對沒有現有程式庫的 FIDL ID 設下限制。 不會變更 FIDL 語言、IR (目前仍為 1)、繫結、風格指南或評分量表。

實際上,ID 是由一連串的字詞組成。常見的彙整字詞方法是 CamelCase (從左到大寫的組合為文字邊界),而 snake_case 則使用一或多個底線 (_) 來分隔字詞。

ID 應轉換為標準格式,以便進行比較。這會是 lower_snake_case 表單,並保留原始格式的字詞分隔。字詞會毀損 (1) 包含底線、(2) 從小寫或數字轉換到大寫的文字,以及 (3) 在從大寫轉換成小寫之前。

在 FIDL 中,識別碼必須以原始格式使用。 因此,如果類型名稱為 FooBar,嘗試將其稱為 foo_bar 就會發生錯誤。

以下為執行這項轉換的簡易演算法,請使用 Python2

def canonical(identifier):
    last = '_'
    out = ''
    for i, c in enumerate(identifier):
        is_next_lower = i + 1 < len(identifier) and identifier[i+1].islower()
        if c == '_':
            if last != '_':
                out += '_'
        elif (((last.islower() or last.isdigit()) and c.isupper())
              or (last != '_' and c.isupper() and is_next_lower)):
            out += '_' + c.lower()
        else:
            out += c.lower()
        last = c
    return out

以下列舉幾個可能的譯文語言範例:

FIDL ID 標準形式 C++ Rust 查看 飛鏢
foobar foobar foobar foobar Foobar foobar_
foo_bar foo_bar foo_bar foo_bar FooBar fooBar_
foo__bar foo_bar foo_bar foo_bar FooBar fooBar_
FooBar foo_bar foo_bar foo_bar FooBar fooBar_
fooBar foo_bar foo_bar foo_bar FooBar fooBar_
FOOBar foo_bar foo_bar foo_bar FooBar fooBar_

導入策略

系統會更新前端編譯器,檢查每個新 ID 的標準格式,沒有與其他 ID 的標準格式相衝突。

下一個版本的 FIDL IR 應以標準名稱 (而非原始名稱) 整理,但原始名稱將做為宣告欄位。如果我們可以避免在產生的繫結中使用未經修改的名稱,系統就會將原始名稱從 IR 捨棄。

人體工學

這能編碼實務上現有的 FIDL 語言限制。

說明文件與範例

系統會更新 FIDL 語言說明文件,說明這項限制。這樣會擴大納入上方「Design」部分中的大部分內容。

由於本提案只是對現有做法進行編碼,因此範例和教學課程不會受到影響。

回溯相容性

任何可能導致這項變更的現有 FIDL 程式庫違反我們的樣式指南,而且無法用於許多語言繫結。這不會改變用於計算序數的 ID 格式。

效能

這會對前端編譯器產生微乎其微的成本,

安全性

沒有影響。

測試

fidlc 中有許多關於標準化演算法實作的測試。此外,您也將執行 fidlc 測試,確保宣告衝突的 ID 時會發生錯誤,並確保原始名稱必須用於參照宣告。

缺點、替代方案和未知

其中一種做法是不執行任何動作。一般來說,我們在非 C++ 產生的繫結中發現這些問題,是建構失敗。由於 Rust 在 fuchsia.git 中較常用,因此可能會降低衝突至其他花瓣的機率。這類問題對我們來說並不罕見。

標準化演算法雖然簡單,但有一個無法忍受的失敗情況,例如 UPPER_SNAKE_CASE ID 中的混合英數字元字詞可能都無法正常運作。例如 H264_ENCODERh264_encoder,但 A2DP_PROFILEa2_dp_profile。這是因為演算法將數字視為小寫英文字母。 由於 H264Encoder 應標準化為 h264_encoder,因此我們必須分割數字之間的轉換。沒有小寫英文字母的 ID 可能具有特殊大小寫 (只有底線),但這會增加演算法的複雜度,並可能用於心理模型。

標準格式可以是字詞清單,而非 lower_camel_case 字串。兩者是對等的,而且在實務上會簡化為字串來管理。

我們可以使用 ID 的標準格式來產生序數。這會帶來一項破壞性變更,沒有明顯的好處。假如未來有日子中斷標記,我們可能就會視為發生變化。

初次遭拒,以及第二次審查

在 2019 年 4 月 18 日第一次審查期間,該 FTP 遭到拒絕,原因如下。

  • 兩個對立觀點探討解決問題的觀點。
  • 設法建立指定語言的限制模型,盡可能在 FIDL 中維持最大彈性,即使該樣式與建議樣式不同也一樣。這就是這個 FTP 採取的做法。
    • 優點:相較於 Fuchsia,針對 FIDL 最終用途的彈性,僅從程式設計語言的角度來看,
    • 缺點:範圍規則較為複雜,系統不會強制執行樣式,但建議使用 (例如透過程式碼檢查)。因此,這可能導致合作夥伴建構的 API 不符合所需的 Fuchsia 樣式指南,因為這類 API 不需要執行,也不必遵循程式碼檢查。
  • 直接在語言中強制執行樣式限制,避免問題類別。
    • 優點:已強制執行樣式、開發人員告知要如何編譯或不編譯內容。
    • 缺點:在語言定義中提供風格選擇值,較爬升高的山丘,適合使用 FIDL 的新手開發人員。
  • → 我們拒絕了提案,而是選擇直接以該語言強制執行樣式的做法。
  • → 這裡是正式提案,旨在實現這個目標,並清楚說明所有相關層面 (例如 uint8 應為 Uint8vector<T> 應為 Vector<T>?)

我們根據下列觀察結果決定推翻這項決定:

  • 核心 API 現已說明 FIDL。這促使我們在去年 10 月重新開放 ID 唯一性問題,基本上反而徹底改變了決定,允許「C-style」和「FIDL-style」同時存在。這項行為目前是由 Fidl Linter 進行檢查。

  • 我們看過其他用途,將 FIDL 推送至一般的傳輸方式,也可能為了更妥善地支援這些網域,並可能還會使用本機樣式規則。

  • ID 衝突仍是一大問題,而建立目標語言限制模型也是 FIDL 工具鍊中可明確識別的缺口。

先前的圖片和參考資料

在 proto3 的類似規則中,系統會套用 JSON 編碼的 lowerCamelCase 名稱。



  1. 在新版 IR 結構定義之前,其名稱可能會附加採用其他結構的名稱,而非目前存在的完整名稱。 

  2. 這個演算法在接受 FTP 後於 2020 年 6 月 3 日修改,以便更符合 FIDL 後端的現有行為。