更新 VMO 檔案格式

本文說明如何更新或擴充元件檢查檔案格式

擴充格式時,請務必避免破壞任何現有功能, 尤其是檢查讀取器和驗證測試但將所有變更封裝成單一 所以可能讓人感到無所適從一般來說,變更 VMO 格式的鏈結中應包含 5 到 9 個變更或步驟:

  1. (可能不適用) 請更新 VMO 格式說明文件以選擇類型編號
  2. 更新 Rust 讀取器。
  3. 更新 C++ 讀取器。
  4. 更新 Rust 寫入器。
  5. 更新 C++ 寫入器。
  6. (可能) 更新驗證器。
  7. 更新說明文件。
  8. (非變更)(選用) 傳送功能公告。

選擇類型編號

在「檢查檔案格式」中查看類型表格,然後選擇可用的類型編號。目前規格中總共有 256 種可能類型。

如要預留新類型,請更新檢查檔案格式

實作

在沒有另一個元件支援的情況下,測試讀取器或寫入器會很麻煩,而且在沒有讀取器和寫入器的情況下,很難取得適當的區塊層級 API。

如要測試讀取器和寫入器,請按照下列步驟操作:

  1. 請選擇一種語言,並使用該語言設計及實作功能,並使用單元測試模擬 API 的實際用途。

  2. 將變更分成不同的讀者和作者異動,並將作者堆疊在 例如讀者

    此時,讀取器中依賴 Writer API 的測試可能會在讀取器變更時中斷。

  3. 將基底重新設為該變更,並使用較低層級的功能重寫測試 (保留原始版本的測試)。

    通常,您可以將所有變更內容加入讀取器變更中,這麼做雖然可行,但會讓讀取器 API 的測試變得雜亂。

  4. 測試會變得難看。將基底重新納入作者變更,並移除修改過的測試,改用以高階 API 編寫的原始測試。

  5. 請使用兩項變更做為參考,並以第二種語言複製。

  6. (選用) 視變更內容而定,您可能需要更新 validator 我們就能封鎖這些程式碼

以下各節將概述如何整合各項變更,但在實務上將這些內容視為提示 ,在分割上述設計之前,請合併整個系統。

更新 Rust 實作

本節中的範例會建立名為 MyFoo 的新類型。

設定

  1. 納入測試:
fx set core.x64 --with //src/lib/diagnostics:tests
  1. 執行測試:

fx test inspect-format-tests fuchsia-inspect-tests

讀者變更

Bitfield 更新

  1. 如果定義新的區塊類型,請更新 BlockType 列舉

  2. 更新為 BlockType 定義的方法和函式。

  3. 如要變更現有區塊中的欄位或建立新的 BlockType,請更新 位元版面配置

  4. 執行 inspect-format-tests 以驗證變更編譯:

fx test inspect-format-tests
  1. 更新區塊定義,加入讀取及寫入新欄位的方法。目前適合在區塊程式庫中納入寫入功能。 沒什麼事來編寫讀者測試

  2. 編寫運用新功能的區塊測試。

  3. 編寫測試,對區塊的前 8 至 16 個位元組做出斷言。

    通常這表示將預期內容寫入含有十六進制值的 &[u8],並斷言其與區塊用作容器的緩衝區相等。

更新讀取器

您可以在 mod.rs 中找到讀取器程式碼。由於高階 API 編寫工具尚未存在,因此這項變更的測試可能會比較棘手。

作者變更

狀態

主要變更會影響 State 功能。這樣就能分配封鎖條件,並將封鎖條件轉換為新的類型。 如果您只修改現有區塊,應該就只有 並做出相應變更

建立新的值類型

您可以使用類型目錄為類型新增檔案。

  1. 在已建立的檔案中建立新類型。以現有類型為例,類型一律可存取內部 State。您可以用這個方式建立 在新型別上呼叫方法,呼叫在 State 中建立的方法。

  2. 新增方法至 Node,以便建立新類型。

  3. 確認類型在 VMO 中具有 RAII 語意。如果您的類型是 輸入值時,可能是系統自動複製現有內容 請在步驟 1 輸入

最後,回到 Reader 變更來更新測試,以使用新的 API!

更新 C++ 實作

本節的範例會建立名為 MyFoo 的新類型。

如上所述,這部分應該在 Gerrit 中應進行兩項變更。

設定

  1. 包含測試:
,瞭解如何調查及移除這項存取權。
fx set core.x64 --with //zircon/system/ulib/inspect:tests
  1. 執行測試。
fx test inspect-cpp-unittest

讀者變更

位元欄更新

本節說明如何定義新型別的 Bitfields。

更新封鎖定義

  1. BlockType 變更為包含新的類型。例如:kMyFoo = #;

  2. 如果您的類型需要新的標頭 (通常是 VALUE 的情況下), 使用結構體定義類型標頭位元欄位。例如: struct MyFooBlockFields final : public BlockFields

  3. 如果您的類型需要新的酬載 (需要使用區塊的第二個 8 個位元組), 使用結構體定義型別的酬載位元欄位。例如:struct MyFooBlockPayload final

  4. 如果您的類型包含列舉項目 (例如格式), 在 block.h 頂端定義新的列舉。例如:enum class MyFooBlockFormat : uint8_t

實作類型讀取器

本節說明如何將新類型設為可讀取。

根據類型更新檢查階層

值 (Node 的子項)

  1. 請使用新的類型編號更新 PropertyFormat 列舉。這序列 這個特定的列舉,不需要符合您選擇的格式類型序數。

  2. 建立新的值類型。例如: using MyFooValue = internal::Value<T, static_cast<size_t>(PropertyFormat::kMyFoo)>;

  3. 使用新值更新 PropertyValue 變化版本。注意:fit::internal::variant 中的索引必須與 PropertyFormat 的值相符。

不是值

  1. 您需要在階層檔案中建立自己的記憶體內表示物件。
  1. 更新實際讀取器

  2. 更新 InnerScanBlocks 即可分派類型。如果您要建立新的 Property,可能只需要新增 BlockType

  3. 如果您需要自訂剖析器,請實作 InnerParseMyFoo,該方法會取得父項 (如有必要) 和掃描區塊的指標。

修改者

類型包裝函式宣告

本節說明如何為新類型宣告 C++ RAII 樣式的包裝函式。

類型包裝函式包含該類型擁有的區塊索引。您必須為 並為這些區塊實作作業,包括建立及刪除 狀態動作更新

更新寫入者類型定義

判斷您是否能重複使用現有的包裝函式,或是否需要自訂類型:

重複使用

  1. 如果您需要支援「新增」、「減號」及「設定:using MyFoo = internal::NumericProperty<T>」, 其中 T 是這些作業的引數類型。

  2. 如果您需要支援 組,請設定:using MyFoo = internal::Property<T>,其中 T 是引數 設為「設定」類型

  3. 如果您需要支援陣列上的數值運算:using MyFood = internal::ArrayProperty<T>,其中 T 是陣列中槽位的引數類型。

  4. 如果您需要支援插入直方圖:using MyFoo = internal::{Linear,Exponential}Histogram<T>,其中 T 是插入的引數。

訂製

  1. 建立新的類型包裝函式。例如 class MyFoo final

  2. 確認課程已將 internal::State 做為好友課程。注意:請參閱 class Link 可複製的起點

狀態動作更新

State 類別是所有類型所有作業的實際實作方式。這個區段 會說明如何實作您包裝函式實作所需的作業。

  1. 更新 State 標頭

    1. 新增 Create 和 Free 方法。例如:MyFoo CreateMyFoo(<args>); void FreeMyFoo(MyFoo* property);,其中 args 通常包含名稱、父項和一些初始值。

    2. 為您需要在類型上支援的每項作業新增方法。舉例來說 您可以設定 void SetMyFoo(MyFoo* property, T),其中 T 和您的 更新為 types.h

  2. 更新 State

    1. 實作新類型的各項方法。不同類型的實作方式各異。本節將概略說明每個方法的功用:

      • MyFoo CreateMyFoo(Args...) 負責分配多個區塊,設定 值,並傳回在 MyFoo 中包裝的引數。您可以使用私人建構函式,從所包裝的 BlockIndex 物件建立 MyFoo。我們提供各種內部輔助程式,以簡化這項作業。如需範例,請參閱 CreateIntProperty

      • void FreeMyFoo(MyFoo* property) 負責釋放由 MyFoo 包裝的所有區塊。有時候,將有特殊的訂購規定或更新 去除方塊請參閱 InnerFreeValue,瞭解如何釋放值。

      • 作業 (例如 void SetMyFoo(MyFoo* property, T value)) 會變更區塊的值 系統分配給 MyFoo 來執行這項作業。如需範例,請參閱 SetIntProperty

實作類型包裝函式

本節說明如何實作先前宣告的包裝函式方法。

  1. 更新寫入者類型定義

    • 如果您使用現有的範本類型,就必須為新基礎覆寫每種方法 類型:T。舉例來說,如果您輸入 using MyFoo = internal::Property<T>,就會寫入: template<> void internal::Property<T>::OPERATION(...) { ... }

    • 如果您建立了自己的類型,只要為宣告的方法建立定義即可。您需要具備 :

      • 讓建構函式呼叫 state_->CreateMyFoo(...);

      • 將解構函式呼叫 state_->FreeMyFoo(...);

      • 讓其他方法呼叫狀態上的對應實作。

      • 請讓所有建構函式和方法在呼叫前,檢查 state_ 並非空值。

實作測試

  1. 針對低層級作業的測試,更新狀態單元測試

  2. 針對高階讀者進行測試更新讀取器單元測試

變更鏈結範例

  1. C++ Reader
  2. Rust Reader
  3. Rust Writer
  4. Rust 驗證工具異動
  5. C++ 驗證工具變更
  6. 說明文件更新