本文說明如何更新或擴充元件檢查檔案格式。
擴充格式時,請務必避免破壞任何現有功能, 尤其是檢查讀取器和驗證測試但將所有變更封裝成單一 所以可能讓人感到無所適從一般來說,變更 VMO 格式的鏈結中應包含 5 到 9 個變更或步驟:
- (可能不適用) 請更新 VMO 格式說明文件以選擇類型編號。
- 更新 Rust 讀取器。
- 更新 C++ 讀取器。
- 更新 Rust 寫入器。
- 更新 C++ 寫入器。
- (可能) 更新驗證器。
- 更新說明文件。
- (非變更)(選用) 傳送功能公告。
選擇類型編號
在「檢查檔案格式」中查看類型表格,然後選擇可用的類型編號。目前規格中總共有 256 種可能類型。
如要預留新類型,請更新檢查檔案格式。
實作
在沒有另一個元件支援的情況下,測試讀取器或寫入器會很麻煩,而且在沒有讀取器和寫入器的情況下,很難取得適當的區塊層級 API。
如要測試讀取器和寫入器,請按照下列步驟操作:
- 請選擇一種語言,並使用該語言設計及實作功能,並使用單元測試模擬 API 的實際用途。 
- 將變更分成不同的讀者和作者異動,並將作者堆疊在 例如讀者 - 此時,讀取器中依賴 Writer API 的測試可能會在讀取器變更時中斷。 
- 將基底重新設為該變更,並使用較低層級的功能重寫測試 (保留原始版本的測試)。 - 通常,您可以將所有變更內容加入讀取器變更中,這麼做雖然可行,但會讓讀取器 API 的測試變得雜亂。 
- 測試會變得難看。將基底重新納入作者變更,並移除修改過的測試,改用以高階 API 編寫的原始測試。 
- 請使用兩項變更做為參考,並以第二種語言複製。 
- (選用) 視變更內容而定,您可能需要更新 validator 我們就能封鎖這些程式碼 
以下各節將概述如何整合各項變更,但在實務上將這些內容視為提示 ,在分割上述設計之前,請合併整個系統。
更新 Rust 實作
本節中的範例會建立名為 MyFoo 的新類型。
設定
- 納入測試:
fx set core.x64 --with //src/lib/diagnostics:tests
- 執行測試: 
fx test inspect-format-tests fuchsia-inspect-tests
讀者變更
Bitfield 更新
- 如果定義新的區塊類型,請更新 - BlockType列舉。
- 更新為 - BlockType定義的方法和函式。
- 如要變更現有區塊中的欄位或建立新的 - BlockType,請更新 位元版面配置。
- 執行 - inspect-format-tests以驗證變更編譯:
fx test inspect-format-tests
- 更新區塊定義,加入讀取及寫入新欄位的方法。目前適合在區塊程式庫中納入寫入功能。 沒什麼事來編寫讀者測試 
- 編寫運用新功能的區塊測試。 
- 編寫測試,對區塊的前 8 至 16 個位元組做出斷言。 - 通常這表示將預期內容寫入含有十六進制值的 - &[u8],並斷言其與區塊用作容器的緩衝區相等。
更新讀取器
您可以在 mod.rs 中找到讀取器程式碼。由於高階 API 編寫工具尚未存在,因此這項變更的測試可能會比較棘手。
作者變更
狀態
主要變更會影響 State 功能。這樣就能分配封鎖條件,並將封鎖條件轉換為新的類型。
如果您只修改現有區塊,應該就只有
並做出相應變更
建立新的值類型
您可以使用類型目錄為類型新增檔案。
- 在已建立的檔案中建立新類型。以現有類型為例,類型一律可存取內部 - State。您可以用這個方式建立 在新型別上呼叫方法,呼叫在- State中建立的方法。
- 新增方法至 - Node,以便建立新類型。
- 確認類型在 VMO 中具有 RAII 語意。如果您的類型是 輸入值時,可能是系統自動複製現有內容 請在步驟 1 輸入 
最後,回到 Reader 變更來更新測試,以使用新的 API!
更新 C++ 實作
本節的範例會建立名為 MyFoo 的新類型。
如上所述,這部分應該在 Gerrit 中應進行兩項變更。
設定
- 包含測試:
fx set core.x64 --with //zircon/system/ulib/inspect:tests
- 執行測試。
fx test inspect-cpp-unittest
讀者變更
位元欄更新
本節說明如何定義新型別的 Bitfields。
更新封鎖定義。
- 將 - BlockType變更為包含新的類型。例如:- kMyFoo = #;
- 如果您的類型需要新的標頭 (通常是 - VALUE的情況下), 使用結構體定義類型標頭位元欄位。例如:- struct MyFooBlockFields final : public BlockFields。
- 如果您的類型需要新的酬載 (需要使用區塊的第二個 8 個位元組), 使用結構體定義型別的酬載位元欄位。例如: - struct MyFooBlockPayload final。
- 如果您的類型包含列舉項目 (例如格式), 在 block.h 頂端定義新的列舉。例如: - enum class MyFooBlockFormat : uint8_t。
實作類型讀取器
本節說明如何將新類型設為可讀取。
根據類型更新檢查階層:
值 (Node 的子項)
- 請使用新的類型編號更新 - PropertyFormat列舉。這序列 這個特定的列舉,不需要符合您選擇的格式類型序數。
- 建立新的值類型。例如: - using MyFooValue = internal::Value<T, static_cast<size_t>(PropertyFormat::kMyFoo)>;
- 使用新值更新 - PropertyValue變化版本。注意:- fit::internal::variant中的索引必須與- PropertyFormat的值相符。
不是值
- 您需要在階層檔案中建立自己的記憶體內表示物件。
- 更新實際讀取器。 
- 更新 - InnerScanBlocks即可分派類型。如果您要建立新的- Property,可能只需要新增- BlockType。
- 如果您需要自訂剖析器,請實作 - InnerParseMyFoo,該方法會取得父項 (如有必要) 和掃描區塊的指標。
修改者
類型包裝函式宣告
本節說明如何為新類型宣告 C++ RAII 樣式的包裝函式。
類型包裝函式包含該類型擁有的區塊索引。您必須為 並為這些區塊實作作業,包括建立及刪除 狀態動作更新。
更新寫入者類型定義。
判斷您是否能重複使用現有的包裝函式,或是否需要自訂類型:
重複使用
- 如果您需要支援「新增」、「減號」及「設定: - using MyFoo = internal::NumericProperty<T>」, 其中- T是這些作業的引數類型。
- 如果您需要支援 組,請設定: - using MyFoo = internal::Property<T>,其中- T是引數 設為「設定」類型
- 如果您需要支援陣列上的數值運算: - using MyFood = internal::ArrayProperty<T>,其中- T是陣列中槽位的引數類型。
- 如果您需要支援插入直方圖: - using MyFoo = internal::{Linear,Exponential}Histogram<T>,其中- T是插入的引數。
訂製
- 建立新的類型包裝函式。例如 - class MyFoo final。
- 確認課程已將 - internal::State做為好友課程。注意:請參閱- class Link可複製的起點
狀態動作更新
State 類別是所有類型所有作業的實際實作方式。這個區段
會說明如何實作您包裝函式實作所需的作業。
- 更新 - State標頭:- 新增 Create 和 Free 方法。例如: - MyFoo CreateMyFoo(<args>); void FreeMyFoo(MyFoo* property);,其中- args通常包含名稱、父項和一些初始值。
- 為您需要在類型上支援的每項作業新增方法。舉例來說 您可以設定 - void SetMyFoo(MyFoo* property, T),其中- T和您的 更新為 types.h
 
- 更新 - State:- 實作新類型的各項方法。不同類型的實作方式各異。本節將概略說明每個方法的功用: - MyFoo CreateMyFoo(Args...)負責分配多個區塊,設定 值,並傳回在- MyFoo中包裝的引數。您可以使用私人建構函式,從所包裝的- BlockIndex物件建立- MyFoo。我們提供各種內部輔助程式,以簡化這項作業。如需範例,請參閱- CreateIntProperty。
- void FreeMyFoo(MyFoo* property)負責釋放由- MyFoo包裝的所有區塊。有時候,將有特殊的訂購規定或更新 去除方塊請參閱- InnerFreeValue,瞭解如何釋放值。
- 作業 (例如 - void SetMyFoo(MyFoo* property, T value)) 會變更區塊的值 系統分配給- MyFoo來執行這項作業。如需範例,請參閱- SetIntProperty。
 
 
實作類型包裝函式
本節說明如何實作先前宣告的包裝函式方法。
- 更新寫入者類型定義: - 如果您使用現有的範本類型,就必須為新基礎覆寫每種方法 類型: - T。舉例來說,如果您輸入- using MyFoo = internal::Property<T>,就會寫入:- template<> void internal::Property<T>::OPERATION(...) { ... }
- 如果您建立了自己的類型,只要為宣告的方法建立定義即可。您需要具備 : - 讓建構函式呼叫 - state_->CreateMyFoo(...);
- 將解構函式呼叫 - state_->FreeMyFoo(...);
- 讓其他方法呼叫狀態上的對應實作。 
- 請讓所有建構函式和方法在呼叫前,檢查 - state_並非空值。