RFC-0195:Text API 中的位置和範圍

RFC-0195:文字 API 中的位置和範圍
狀態已接受
領域
  • HCI
說明

說明如何在文字編輯 API 中使用 Unicode 純量值做為位置和範圍的基本單位。

問題
蓋爾特變化
作者
審查人員
提交日期 (年-月-日)2022-08-26
審查日期 (年-月-日)2022-10-25

摘要

我們建議 fuchsia.input.text API 應使用 Unicode 純量值做為其原子單位 文字編輯位置和範圍 (例如插入點和選項)。

提振精神

fuchsia.input.text 命名空間會提供 FIDL 通訊協定可用於編輯文字 跨執行階段實作文字欄位、Input 方法編輯器 (IME)、複製及貼上、自動更正和相關功能。 這些 API 包含多種方法,可用於擷取、選取和 修改文字範圍設計這些方法時,系統扮演了 API 必須標準化為 Unicode 字串建立索引。這樣 舉例來說,如果在 Flutter 中實作螢幕小鍵盤 指示 Chromium 網頁檢視畫面中的文字方塊「刪除三個字元」。 。」鍵盤和瀏覽器是否符合「三個」 字元"以及插入點目前的位置

Fuchsia 的樹狀結構內執行階段目前對於 字串操作單位應為 (請參閱 既有藝術與參考資料)Kubernetes 提供的標準 SDK 這也受到傳統設計選擇的影響 不符合現代 Unicode 標準的案例

因為國際化的文字編輯功能 對現代社會來說至關重要 面向使用者的作業系統,但由於目前沒有統一的 因此 Fuchsia 把握機會改善 為此,請自行選擇其 Cross-runtime API 的單一標準 以確保語氣合理且沒有受到傳統設計 的影響

此外,Fchisia 的文字編輯 API 可做為互通性使用 仍能將容器放在多個獨立執行階段中 因此必須設計明確定義的介面 請務必一致,但不想標準化任何 一個執行階段

相關人員

講師:abarth@google.com

審查者:

  • Fuchsia HCI:neelsa@google.com、fmil@google.com

  • 安全性:pesk@google.com

  • 隱私權:enoharemaien@google.com

  • Chromium:wez@google.com

  • Flutter:jmccandless@google.com、gspencer@google.com

諮詢:quiche@google.com

社交

這項設計以 Google 文件的形式,在 Fuchsia HCI 團隊中社交化,某些人也在 以 RFC CL 格式張貼評論者的情況。

設計

下列關鍵字:「必須」、「不得」、「必要」、「應」、「不應」、「應該」、「應該」、 「不應該」、「建議」、「可能」和「選用」基本上就是 解譯 IETF RFC 2119

背景

請參閱 FIDL API 可讀性評分量表 >字串編碼

FIDL 字串是代表 UTF‐8 編碼的位元組序列 Unicode 文字。

有數種單位可以劃分字串。

  • Unicode 純量值:在 Unicode 中,文字的基本部分是「Unicode」 純量值」,是 [0x0, 0xD7FF], [0xE000, 0x10FFFF] 範圍內的整數,可對應至「抽象字元」。

    萬國碼純量值 Unicode 碼點,也就是格式為 範圍:[0x0, 0x10FFFF]。從 Unicode 中排除的碼點 純量值 [0xD800, 0xDFFF] 稱為 代理碼點。這些 僅供 UTF-16 編碼的實作詳細資料使用,無法 來代表任何指派的字元

  • Byte:將字串分成位元組的輸出內容,取決於編碼方式。 舉例來說,FIDL 字串使用的 UTF‐8 編碼為不定長度 編碼,每個純量值則由 1 到 4 個位元組的序列表示。 (例如,k 是一位元組,ك 是 2 個位元組, 是三個位元組,𐤊 是 4 個位元組)。UTF‐8 標準會指定如何剖析 並判斷新純量值的開始位置。因為 UTF-8 變數長度編碼,系統無法判斷 純量值 (使用 UTF‐8 字串) 或跳到第 n 純純量值時,使用 可以傳遞一致的回應

  • 圖表叢集:某些 Unicode 純量值的組合, 合併成一個使用者感知的「字元」 在技術上稱為「圖表集」例如字母 含變音符號 (á̡),搭配性別和膚色選取器的臉部表情符號 (💂🏽‍♀️) 以及雙字母的國家/地區代碼 (由兩個字母組成) 標記表情符號 (🇦🇺)。 將純量值合併至 Grapheme 叢集的適用規則僅適用於特定情境 並取決於從 Unicode 字元資料庫讀取的屬性為 因此,無論是哪個版本 Unicode 標準。

雖然與 FIDL 及其 UTF-8 字串沒有直接關聯,但有許多舊版 使用 UTF‐16 編碼的執行階段,有一個額外的除法選項:

  • UTF‐16 編碼單位:在 UTF‐16 編碼中,每個萬國碼純量值都是 編碼為一或兩個 2 位元組序列 (稱為 UTF‐16「編碼單位」)。 UTF‐16 標準會指定如何從編碼單位的位元中決定 是單一代碼單位純量值,還是兩碼單位的一部分 代理值配對

設計

fuchsia.input.text 中,位於代表 將一或多個索引轉換為字串,基本單位必須是單一 Unicode 純量值

舉例來說,在以下假想方法中,Range 是按照字詞定義 Unicode 純量值從字串或文字開頭的位置 ] 欄位。

protocol ReadableTextField {
    /// Retrieves part of the contents of the text field.
    GetText(struct {
        range Range;
    }) -> (struct {
        // Note that FIDL string field sizes are specified in bytes
        // https://fuchsia.dev/fuchsia-src/reference/fidl/language/language#strings
        contents string:MAX_STRING_SIZE;
    }) error TextFieldError;
};

type Range = struct {
    /// The index of the first scalar value in the range.
    start uint32;
    /// The index _after_ the last scalar value in the range.
    end uint32;
};

如果文字欄位包含 abcd😀ef🇦🇺gh 字串,則要求的範圍為 [2, 8) 會傳回子字串 cd😀ef🇦。(請注意,圖表叢集 🇦🇺 會 分為 🇦🇺)。

實作

在內部,實作者可能會使用任一個 Unicode 字串編碼和索引 其所選程式設計語言中的支援或便利性。 程式庫

不過,fuchsia.input.text 中通訊協定的所有實作項目。

  • 「必須」使用萬國碼 (Unicode) 純量來正確解讀文字位置和範圍 值索引。
  • 必須傳送文字編輯指令給其他 fuchsia.input.text 會依據 Unicode 純量值索引實作。

供參考:

  • 在 Rust 中,Unicode 純量值是單一 charString&str 可支援 String::chars()

  • 在 Dart 中,這是 rune。字串的 Unicode 純量值可以疊代 使用 String.runes 屬性。

  • 從 C++ 17 開始,標準程式庫的公用程式操控 Unicode 文字 不完整,因此將 icu::UnicodeStringicu::StringCharacterIterator 是 建議改為使用舉例來說,字串中的 n 純量值可以是 使用 setIndex32(n) 擷取。

成效

使用可變長度編碼 (例如 UTF‐8 或 Rust) 的執行階段; 以 UTF‐16 (例如 Dart) 做為字串的字串,透過 萬國碼純量值是一種線性時間作業。(這只是 用於 UTF‐32 和類似的固定長度編碼的常數時間作業, 且不常使用)。

適用於經常存取字串長度並預測有無相符結果的用途 因此建議您快取長度值 預先處理字串,以達到「變形」固定時間。

人體工學

萬國碼純量值具有以下優點:文字編輯 組成:

  • 這樣的精細程度可避免系統分割 UTF‐8 編碼 字元轉換為無效的位元組序列。
  • 如有需要,可在圖表叢集「內」編輯。例如: 輸入「á」後(「a」後面加上「◌」),可用來刪除倒距 而非基本字母。

詳情請見 缺點、替代方案和未知 來比較其他選項

回溯相容性

此 RFC 涉及新的文字編輯 API,而此 API 是從 Fuchsia 平台的一環。我們預期 相容性問題,因此除了完成轉換前的初始工作之外, FIDL API 的文字位置表示法,以及在任何情況下偏好的表示法 在特定語言執行階段期間

安全性考量

根據整個 Unicode 純量值 (而非位元組或位元組) 操控文字 UTF-16 程式碼單位會降低字串無效的可能性 遭到截斷。

按萬國碼 (Unicode) 純量值進行解處理可能會導致分割 石墨黑星團有時是理想的路線 (請參閱人體工學)。 但如果分心,可能會導致極端案例 並輸入變更內容

但由於石墨分群相依,因此請務必接受這項缺點 啟用 Unicode 編碼,甚至需要經過特別的實作調整 因此,使用不同 Unicode 程式庫或版本的用戶端 字串長度不一致,導致資料損毀。

隱私權注意事項

除了上述的 RFC 規範之外,也沒有任何新的隱私權注意事項 就處理使用者提供的文字而言,已有一些隱私權注意事項。

測試

fuchsia.input.text API 的實作者會負責寫入 測試適用的單元和整合測試。這個 RFC 的 均應涵蓋這些測試

視可使用的功能而定 Fchsia 的相容性測試:導入 我們可能會測試文字編輯 API,擴大這些 API 的相容性。適用對象 例如,測試可能會傳送一系列文字編輯指令給用戶端 再驗證產生的文字 欄位內容符合預期。

我們建議實作人員在測試資料中加入非 ASCII 字串, 包括:

  • 包括多程式碼點 Grapheme 叢集
    • 單一字元結合多個變音符號
    • 加上膚色和/或性別修飾語的表情符號
    • 旗幟表情符號

說明文件

fuchsia.input.text 類別的 API 說明文件會明確醒目顯示 各種資料類型 (包括字串位置、範圍和) 的單位 長度。

缺點、替代方案和未知

位元組

優點

  • 在 FIDL 欄位宣告中,string 個長度為 以位元組的形式明確定義
  • 使用位元組可讓您更容易理解記憶體中的大小。
  • 陣列存取位元組陣列為 O(1)。

缺點

  • 需要額外驗證,確保位元組序列構成 有效的 UTF‐8。

  • 容易不小心將 UTF‐8 字元分割為不完整 (且 因此無效) 位元組序列。

  • 除非已知,否則以一個位元組來移動位置並不算有用 剛才編輯的文字僅包含 ASCII 字元。

圖表叢集

優點

  • 在文字編輯器中,插入點通常都會放在石墨色叢集上 界定範圍

  • 依據整個圖表叢集選取文字,可確保複雜的表情符號不會 不小心以容易使用的方式分割 (例如使用 點,👮🏽‍♀️ (中間膚色的女性警察表情符號) 可以拆分為 POLICE OFFICER (U+1F46E)EMOJI MODIFIER FITZPATRICK TYPE-4 (U+1F3FD)ZERO WIDTH JOINER (U+200D)FEMALE SIGN (U+2640) VARIATION SELECTOR-16 (U+FE0F))。

缺點

  • 各萬國碼 (Unicode) 版本之間可能出現圖表分群規則 都涉及跨領域的字元屬性資料表查詢 CLDR

    更重要的是,叢集規則組合並未完全由 萬國碼 (Unicode) 版本;可以因導入作業而異 語言之間或語言代碼之間1。透過 FIDL 進行通訊的兩個元件 (例如 也可能是螢幕小鍵盤以及顯示文字方塊的執行階段) 因此可能會導致 試圖操縱的文字範圍。

    石墨色叢集的 Unicode 規格,UAX #29:萬國碼 (Unicode) 文字 區隔明確狀態

    本文件定義了 Grapheme 叢集的預設規格。這項服務 也可以針對特定語言、作業或其他用途進行自訂 情境。例如,你可以依語言調整方向鍵移動 也可以運用特定字型的知識 以精細的方式編輯 個別元件這可能適用於 泰國北部泰姆文 (Lanna) 編輯規定。 同樣地,依元素編輯圖表叢集元素可能也是建議的做法 在某些情況下。例如,在特定系統上,Backspace 鍵 刪除鍵可能會刪除整個程式碼 物件

UTF-16 編碼單位

優點

  • 許多第三方標準程式庫和執行階段都使用 UTF‐16 編碼 。

缺點

  • FIDL 傳輸字串採用 UTF‐8,而非 UTF‐16。隆重推出 透過 FIDL 將編碼單位轉換成文字編輯 API 且由於迫使實作人員強制在內部執行,這樣會造成混淆 至少支援兩種不同的編碼。
  • 與個別位元組一樣,很容易在無意中分割純量值 轉換成無與倫比的 UTF-16 代理值

既有藝術品和參考資料

Flutter

Flutter 似乎已遷移至 在公用 API 中使用 Grapheme 叢集,但說明文件仍然存在 不一致:

  • Dart 的 String 類別說明文件指出 "字串會以 Unicode UTF‐16 編碼單位的序列表示"以及 字串的字元是以 UTF‐16 編碼。解碼 UTF‐16 結合代理值、產生萬國碼 (Unicode) 碼點,暗示 character 代表代碼單位

  • Flutter 不會明確記錄其 TextPositionTextRange 單位,將 偏移定義為 "緊接在字串中位置的字元索引 文字表示法但不定義字元

  • Flutter 的 TextField.maxLength 屬性定義為

    允許匯入的字元數上限 (Unicode 圖表叢集) 。

    以下進一步詳細說明:

    字元
    如需瞭解何謂字元的特定定義,請參閱 character 套件的形式,也就是 Flutter 用來分隔字元。一般而言,即使是複雜的字元 如代理配對和延伸圖譜叢集 會將每個 Flutter 解讀為單一使用者感知的字元。

網路

JavaScript 字元為 UTF‐16 程式碼單位。 RangeSelectionCaretPosition 類別都會處理字元 偏移值

(不過,如果想與 Chromium 執行階段整合, Chromium 內部會使用 UTF-8 編碼字串)。

Android

Android 的 IME API 明確使用 Java char,這些都是 UTF‐16 程式碼單位。 請參閱 android.view.inputmethod.BaseInputConnection.commitText

MacOS 和 iOS

在 Objective-C 中,NSString 說明文件「表示」

NSString 物件會將符合 Unicode 標準的文字字串編碼,以 UTF‐16 編碼單位序列。所有長度、字元索引和範圍都是 以 16 位元平台端對端值表示,並具有索引值 0起。

不過,Swift 類別 String 預設會使用圖表叢集做為 單位,包含額外屬性以公開 Unicode 碼點、UTF‐16 程式碼 單位和位元組

文字編輯相關類別會根據是否使用不同單位 源自 Objective-C 或 Swift UITextInput 通訊協定使用不透明的抽象 類別 UITextRangeUITextPosition,也就是 與實作相關的。

Windows

Windows Core Text 的說明文件將其稱為索引 「應用程式插入位置」,詳情請參閱

以零為基準的數字,表示從開頭的 文字串流位於插入點之前

「字元數」暗示 UTF‐16 程式碼單位 System.Char 類型代表。


  1. 字串 "ch" 中有幾個圖表叢集?在「en-US」中 兩個語言在 cs-CZ (捷克) 中,應為一,因為 'ch' 是 一個圖表