產生 FIDL Rust 箱
您可以透過兩種方式從 FIDL 程式庫產生 FIDL Rust crate:
- 手動使用標準 FIDL 工具鍊。
- 自動使用 Fuchsia 建構系統 (實際上使用標準 FIDL 工具鍊)。這個選項僅適用於 Fuchsia 來源樹狀結構。
程式庫
FIDL library
會對應至名為 fidl_
的 Rust 程式庫 Crate,後面接著是完整的程式庫路徑,其中的點會以底線取代。
舉例來說,如果指定 library
宣告:
library fuchsia.examples;
對應的 FIDL crate 名稱為 fidl_fuchsia_examples
:
use fidl_fuchsia_examples as fex;
特徵
實作 FIDL 執行階段 Crate 中的特徵,即可提供 FIDL Rust Crate 中的部分方法和常數。如要存取這些資源,您必須匯入相應特徵。最簡單的方法是從前奏模組一次匯入所有模組:
use fidl::prelude::*;
前置檔使用 as _
語法重新匯出特徵,因此 glob 匯入作業只會將特徵帶入解析方法和常數的範圍。不會匯入特徵名稱本身。
常數
假設常數如下:
const BOARD_SIZE uint8 = 9;
const NAME string = "Tic-Tac-Toe";
FIDL 工具鍊會產生下列常數:
pub const BOARD_SIZE: u8
pub const NAME: &str
如需 FIDL 原始類型與 Rust 類型的對應關係,請參閱「內建類型」一文。
欄位
本節說明 FIDL 工具鍊如何將 FIDL 類型轉換為 Rust 中的原生類型。這些類型可做為集合類型的成員,或做為通訊協定方法的參數。
內建類型
在下表中,如果同時指定「owned」和「borrowed」變體,則「owned」類型是指在匯總類型中顯示的類型 (例如結構體欄位或向量元素的類型),而「borrowed」類型則是指如果用於做為通訊協定方法參數 (從用戶端的角度) 或回應元組值 (從伺服器的角度) 時,會顯示的類型。之所以區分擁有和借用,是為了充分利用 Rust 的擁有權模式。當您使用 T
類型的參數提出要求時,代理函式呼叫不需要取得 T
的擁有權,因此 FIDL 工具鍊需要產生 T
的借用版本。借用版本通常會使用 &mut
,因為 T
類型可能包含句柄,在這種情況下,FIDL 繫結會在編碼時將句柄設為零,進而修改輸入內容。使用 &mut
而非取得擁有權,可讓呼叫端在輸入值不含句柄時重複使用輸入值。
FIDL 類型 | Rust 類型 |
---|---|
bool |
bool |
int8 |
i8 |
int16 |
i16 |
int32 |
i32 |
int64 |
i64 |
uint8 |
u8 |
uint16 |
u16 |
uint32 |
u32 |
uint64 |
u64 |
float32 |
f32 |
float64 |
f64 |
array<T, N> |
&mut [T; N] (借用)[T, N] (擁有) |
vector<T>:N |
&[T] (借用,當 T 為數值原始類型時)&mut dyn ExactSizeIterator (借用)Vec (擁有) |
string |
&str (借用)String (擁有) |
server_end:P |
fidl::endpoints::ServerEnd<PMarker> ,其中 PMarker 是此通訊協定的標記類型。 |
client_end:P |
fidl::endpoints::ClientEnd<PMarker> 其中 PMarker 是此通訊協定的標記類型。 |
zx.Handle |
fidl::Handle |
zx.Handle:S |
系統會使用對應的句柄類型。例如 fidl::Channel 或 fidl::Vmo |
使用者定義的類型
位元、列舉和表格一律會使用產生的類型 T
進行參照。結構體和聯集可以是必要或選用,並用於擁有的上下文或借用上下文,這表示有四種可能的等同 Rust 類型。對於特定 struct T
或 union T
,類型如下:
自有 | borrowed | |
---|---|---|
必要 | T |
&mut T |
選用 | Option<T> |
Option<&mut T> |
要求、回應和事件參數
當 FIDL 需要產生單一 Rust 類型,用來代表要求、回應或事件的參數 (例如結果類型) 時,會使用以下規則:
- 多個參數會以參數類型的元組表示。
- 單一參數只會使用參數的類型表示。
- 空參數集會以單位類型
()
表示。
類型
位元
假設 bits 定義如下:
type FileMode = strict bits : uint16 {
READ = 0b001;
WRITE = 0b010;
EXECUTE = 0b100;
};
FIDL 工具鍊會產生一組名為 FileMode
的 bitflags
,並使用 FileMode::READ
、FileMode::WRITE
和 FileMode::EXECUTE
旗標。
bitflags
結構體也提供下列方法:
get_unknown_bits(&self) -> u16
:傳回原始值,其中只包含此位元值中的不明成員。對於「嚴格」位元,則會標示為#[deprecated]
,並一律傳回 0。has_unknown_bits(&self) -> bool
:會傳回這個值是否包含任何不明位元。對於「嚴格」位元,會標示為#[deprecated]
,並一律傳回false
。
產生的 FileMode
結構體一律會包含完整的 #[derive]
規則。
使用範例:
let flags = fex::FileMode::READ | fex::FileMode::WRITE;
println!("{:?}", flags);
列舉
給定enum 定義:
type LocationType = strict enum {
MUSEUM = 1;
AIRPORT = 2;
RESTAURANT = 3;
};
FIDL 工具鍊會使用指定的基礎類型產生 Rust enum
,如果未指定任何類型,則會產生 u32
:
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(u32)]
pub enum LocationType {
Museum = 1,
Airport = 2,
Restaurant = 3,
}
使用下列方法:
from_primitive(prim: u32) -> Option<Self>
:傳回與判別值對應的列舉變數Some
(如有),否則傳回None
。into_primitive(&self) -> u32
:傳回基礎判別值。is_unknown(&self) -> bool
:傳回此列舉是否不明。對於嚴格類型,它會標示為#[deprecated]
,並一律傳回false
。
如果 LocationType
是彈性,則會提供下列額外方法:
from_primitive_allow_unknown(prim: u32) -> Self
:從基本值建立列舉的例項。unknown() -> Self
:傳回預留位置未知的列舉值。如果列舉包含標有[Unknown]
的成員,則此方法傳回的值會包含指定不明成員的值。
產生的 LocationType
enum
一律包含完整的 #[derive]
規則。
使用範例:
let from_raw = fex::LocationType::from_primitive(1).expect("Could not create LocationType");
assert_eq!(from_raw, fex::LocationType::Museum);
assert_eq!(fex::LocationType::Restaurant.into_primitive(), 3);
為了提供來源相容性,彈性列舉有一個不明巨集,應用於比對不明成員,而非 _
模式。例如,請參閱 LocationTypeUnknown!()
巨集的使用方式:
match location_type {
fex::LocationType::Museum => println!("museum"),
fex::LocationType::Airport => println!("airport"),
fex::LocationType::Restaurant => println!("restaurant"),
fex::LocationTypeUnknown!() => {
println!("unknown value: {}", location_type.into_primitive())
}
}
不明巨集的運作方式與 _
模式相同,但可設定為擴展至完整比對。這對發現遺漏的個案相當實用。
Structs
假設已宣告 struct:
type Color = struct {
id uint32;
@allow_deprecated_struct_defaults
name string:MAX_STRING_LENGTH = "red";
};
FIDL 工具鍊會產生 Rust struct
:
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Color {
pub id: u32,
pub name: String,
}
系統產生的 Color
struct
會遵循 #[derive]
規則。
使用範例:
let red = fex::Color { id: 0u32, name: "red".to_string() };
println!("{:?}", red);
聯合體
給定union 定義:
type JsonValue = strict union {
1: int_value int32;
2: string_value string:MAX_STRING_LENGTH;
};
FIDL 工具鍊會產生 Rust enum
:
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum JsonValue {
IntValue(i32),
StringValue(String),
}
使用下列方法:
ordinal(&self) -> u64
:傳回 FIDL 類型中指定的有效變數序號。is_unknown(&self) -> bool
:傳回此聯集是否不明。對於非彈性聯合型別,一律會傳回false
。對於嚴格類型,它會標示為#[deprecated]
,並一律傳回false
。
如果 JsonValue
是彈性,則會提供下列額外方法:
unknown_variant_for_testing() -> Self
:建立不明的聯集值。這項設定應僅用於測試。
系統產生的 JsonValue
enum
會遵循 #[derive]
規則。
使用範例:
let int_val = fex::JsonValue::IntValue(1);
let str_val = fex::JsonValue::StringValue("1".to_string());
println!("{:?}", int_val);
assert_ne!(int_val, str_val);
彈性的聯集和未知的變化版本
彈性聯集會產生額外的變化版本,用於代表不明的情況。這個變化版本屬於私人資料,不應直接參照。
為了提供來源相容性,彈性聯集會提供一個不明巨集,應用於比對不明成員,而非 _
模式。例如,請參閱 JsonValueUnknown!()
巨集的使用方式:
match json_value {
fex::JsonValue::IntValue(val) => println!("int: {}", val),
fex::JsonValue::StringValue(val) => println!("string: {}", val),
fex::JsonValueUnknown!() => println!("unknown ordinal: {}", json_value.ordinal()),
}
不明巨集的運作方式與 _
模式相同,但可設定為擴展至完整比對。這對發現遺漏的個案相當實用。
當含有不明變化的聯集的 FIDL 訊息解碼為 JsonValue
時,JsonValue::is_unknown()
會傳回 true。
彈性聯集有自訂 PartialEq
,可讓未知的變數的行為類似於 NaN:不會與任何值 (包括自身) 相等。如需這項決定的背景資訊,請參閱 RFC-0137:在 FIDL 中捨棄不明資料。
在解碼不明變數時,嚴格的聯集會失敗。彈性聯集在解碼不明變種時會成功,但在重新編碼時會失敗。
表格
給定資料表定義:
type User = table {
1: age uint8;
2: name string:MAX_STRING_LENGTH;
};
FIDL 工具鍊會產生具有選用成員的 struct
User
:
#[derive(Debug, PartialEq)]
pub struct User {
pub age: Option<u8>,
pub name: Option<String>,
#[doc(hidden)]
pub __source_breaking: fidl::marker::SourceBreaking,
}
如果解碼期間遇到任何不明欄位,系統會捨棄這些欄位。我們無法存取這些事件,也無法判斷這些事件是否發生。
__source_breaking
成員會指出,在新增欄位時,完整初始化資料表會導致 API 中斷。請改用結構體更新語法,使用 Default::default()
填入未指定的欄位。例如:
let user = fex::User { age: Some(20), ..Default::default() };
println!("{:?}", user);
assert!(user.age.is_some());
同樣地,表格不允許完全比對。您必須改用 ..
語法,才能忽略未指定的欄位。例如:
let fex::User { age, name, .. } = user;
系統產生的 User
struct
會遵循 #[derive]
規則。
內嵌版面配置
產生的 Rust 程式碼會使用fidlc
預留的名稱,用於內嵌版面配置。
衍生
當 FIDL 工具鍊為 FIDL 類型產生新的 struct
或 enum
時,會嘗試從預先定義的實用特徵清單中,derive
盡可能多的特徵,包括 Debug
、Copy
、Clone
等。完整的特徵清單可參閱附錄 A。
對於結構體、聯合體和資料表等匯總類型,系統會從所有可能的派生項目清單開始,然後根據在類型中傳遞的欄位移除部分派生項目,藉此決定派生項目集。舉例來說,透過推導方式包含 vector
的集合型別不會產生 Copy
,而包含 handle
的型別 (也就是未標示為 resource
的型別) 不會產生 Copy
和 Clone
。如有疑問,請參考產生的程式碼,查看特定類型衍生出哪些特徵。如需實作詳細資訊,請參閱附錄 B。
通訊協定
假設有以下通訊協定:
closed protocol TicTacToe {
strict StartGame(struct {
start_first bool;
});
strict MakeMove(struct {
row uint8;
col uint8;
}) -> (struct {
success bool;
new_state box<GameState>;
});
strict -> OnOpponentMove(struct {
new_state GameState;
});
};
與 TicTacToe
互動的主要進入點是 TicTacToeMarker
結構體,其中包含兩個關聯類型:
Proxy
:與非同步用戶端搭配使用的關聯 Proxy 類型。在本例中,這是產生的TicTacToeProxy
類型。同步用戶端應直接使用TicTacToeSynchronousProxy
(請參閱「同步」),而非儲存在TicTacToeMarker
的關聯類型中。RequestStream
:實作此通訊協定的伺服器需要處理的相關要求串流。在這個範例中,這個值是TicTacToeRequestStream
,由 FIDL 產生。
此外,TicTacToeMarker
還具有實作 fidl::endpoints::ProtocolMarker
的下列相關常數:
DEBUG_NAME: &’static str
:適合用於偵錯的服務名稱。
視套用至通訊協定或其方法的通訊協定和方法屬性而定,系統可能會產生其他程式碼。
用戶端
非同步
針對非同步用戶端,FIDL 工具鍊會產生 TicTacToeProxy
結構體,其中包含以下項目:
相關類型:
TicTacToeProxy::MakeMoveResponseFut
:雙向方法回應的Future
類型。這個類型會實作std::future::Future<Output = Result<(bool, Option<Box<GameState>>), fidl::Error>> + Send
。
方法:
new(channel: fidl::AsyncChannel) -> TicTacToeProxy
:為TicTacToe
建立新的 Proxy。take_event_stream(&self) -> TicTacToeEventStream
:從伺服器端取得事件的Stream
(請參閱「事件」)。
實作 fidl::endpoints::Proxy
的方法:
from_channel(channel: fidl::AsyncChannel) -> TicTacToeProxy
:與TicTacToeProxy::new
相同。into_channel(self) -> Result<fidl::AsyncChannel>
:嘗試將 Proxy 轉換回管道。as_channel(&self) -> &fidl::AsyncChannel
:取得對等端的基礎管道參照is_closed(&self) -> bool
:檢查 Proxy 是否已收到PEER_CLOSED
信號。on_closed<'a>(&'a self) -> fuchsia_async::OnSignals<'a>
:取得在 Proxy 收到PEER_CLOSED
信號時完成的 Future。
實作 TicTacToeProxyInterface
的方法:
start_game(&self, mut start_first: bool) -> Result<(), fidl::Error>
:用於 fire and forget 通訊協定方法的 Proxy 方法。它會將要求參數做為引數,並傳回空白結果。make_move(&self, mut row: u8, mut col: u8) -> Self::MakeMoveResponseFut
:雙向方法的 Proxy 方法。它會將要求參數做為引數,並傳回回應的Future
。
如需設定非同步 Proxy 的範例,請參閱 Rust 教學課程。
TicTacToeProxyInterface
特徵可用於測試用戶端程式碼。舉例來說,如果您撰寫的函式會將 &T
做為 T:
TicTacToeProxyInterface
的參數,您可以使用假的 Proxy 類型進行單元測試:
use futures::future::{ready, Ready};
struct FakeTicTacToeProxy {
move_response: (bool, Option<Box<GameState>>),
}
impl TicTacToeProxyInterface for FakeTicTacToeProxy {
fn start_game(&self, mut start_first: bool) -> Result<(), fidl::Error> {
Ok(())
}
type MakeMoveResponseFut = Ready<fidl::Result<(bool, Option<Box<GameState>>)>>;
fn make_move(&self, mut row: u8, mut col: u8) -> Self::MakeMoveResponseFut {
ready(self.move_response.clone())
}
}
處理轉換
這張流程圖說明在 Rust FIDL 生態系統中,用於非同步用戶端的句柄包裝函式類型之間可用的各種轉換。請注意,虛線表示可能失敗的方法或函式。
同步
針對 TicTacToe
通訊協定的同步用戶端,FIDL 工具鍊會使用下列方法產生 TicTacToeSynchronousProxy
結構體:
new(channel: fidl::Channel) -> TicTacToeSynchronousProxy
:透過管道的用戶端端點傳回新的同步 Proxy。假設伺服器端會實作TicTacToe
通訊協定。into_channel(self) -> fidl::Channel
:將 Proxy 轉換回管道。start_game(&self, mut a: i64) -> Result<(), fidl::Error>
:用於立即執行並忘記方法的 Proxy 方法:它會將要求參數做為引數,並傳回空白結果。make_move(&self, mut row: u8, mut col: u8, __deadline: zx::MonotonicInstant) -> Result<(bool, Option<Box<GameState>>), fidl::Error>
:雙向方法的 Proxy 方法。該方法會將要求參數做為引數,後面接著是截止期限參數,該參數會決定方法呼叫會等待多久時間等待回應 (或zx::MonotonicInstant::INFINITE
無限期阻斷)。它會傳回回應參數的Result
。wait_for_event(&self, deadline: zx::MonotonicInstant) -> Result<TicTacToeEvent, fidl::Error>
:阻斷,直到收到事件或截止時間到期為止 (使用zx::MonotonicInstant::INFINITE
可無限期阻斷)。此方法會傳回TicTacToeEvent
enum 的Result
。
如需設定同步 Proxy 的範例,請參閱 Rust 教學課程。
處理轉換
此流程圖說明在 Rust FIDL 生態系統中,同步用戶端的句柄包裝函式類型之間可使用的各種轉換。
伺服器
通訊協定要求串流
為了代表伺服器傳入要求的串流,FIDL 工具鍊會產生實作 futures::Stream<Item
= Result<TicTacToeRequest, fidl::Error>>
和 fidl::endpoints::RequestStream
的 TicTacToeRequestStream
類型。每個通訊協定都有對應的要求資料流類型。
處理轉換
此流程圖說明 Rust FIDL 生態系統中,用於非同步伺服器的句柄包裝函式類型之間可用的各種轉換。
要求列舉
TicTacToeRequest
是代表 TicTacToe
通訊協定可能要求的列舉。其變化版本如下:
StartGame { start_first: bool, control_handle: TicTacToeControlHandle }
:立即執行並忘記要求,其中包含要求參數和控制句柄。MakeMove { row: u8, col: u8, responder: TicTacToeMakeMoveResponder }
:雙向方法要求,其中包含要求參數和回應器。
系統會為每個通訊協定產生一個這樣的列舉。
要求回應者
每個雙向方法都有對應的產生回應者類型,用於伺服器回應要求。在這個只有一個雙向方法的範例中,FIDL 工具鍊會產生 TicTacToeMakeMoveResponder
,提供下列方法:
send(self, mut success: bool, mut new_state: Option<&mut GameState>) -> Result<(), fidl::Error>
:傳送回應。send_no_shutdown_on_err(self, mut success: bool, mut new_state: Option<&mut GameState>) -> Result<(), fidl::Error>
:與send
類似,但如果發生錯誤,不會關閉管道。control_handle(&self) -> &TicTacToeControlHandle
:取得基礎控制項句柄。drop_without_shutdown(mut self)
:捨棄回應器,但不關閉管道。
通訊協定控制點
FIDL 工具鍊會產生 TicTacToeControlHandle
,用於在伺服器端封裝 TicTacToe
通訊協定的用戶端端點。其中包含下列方法:
shutdown(&self)
:關閉管道。shutdown_with_epitaph(&self, status: zx_status::Status)
:發布告別訊息,然後關閉管道。send_on_opponent_move(&self, mut new_state: &mut GameState) -> Result<(), fidl::Error>
:事件的 Proxy 方法,會將事件的參數做為引數,並傳回空白結果 (請參閱「事件」)。
活動
用戶端
針對非同步用戶端接收事件,FIDL 工具鍊會產生 TicTacToeEventStream
,您可以使用 TicTacToeProxy
上的 take_event_stream()
方法取得該事件。TicTacToeEventStream
實作 futures::Stream<Item = Result<TicTacToeEvent,
fidl::Error>>
。
針對同步用戶端接收事件,FIDL 工具鍊會在傳回 TicTacToeEvent
的 TicTacToeSynchronousProxy
上產生 wait_for_event
方法。
TicTacToeEvent
是代表可能事件的列舉。其變化版本如下:
OnOpponentMove { new_state: GameState }
:TicTacToeEvent
事件的判別式。
並提供下列方法:
into_on_opponent_move(self) -> Option<GameState>
:傳回事件的參數Some
,如果變體不符合方法呼叫,則傳回None
。
伺服器
伺服器可以使用與通訊協定相對應的控制項句柄傳送事件。您可以透過從用戶端收到的 TicTacToeRequest
取得控制項句柄。對於立即執行並忘記的方法,控制項句柄可透過 control_handle
欄位取得;對於雙向方法,則可透過回應端的 control_handle()
方法取得。您也可以透過對應的要求串流 (在本例中為 TicTacToeRequestStream
) 取得通訊協定的控制項句柄,因為它實作了 fidl::endpoints::RequestStream
。
結果
對於含有錯誤類型的函式:
protocol TicTacToe {
MakeMove(struct {
row uint8;
col uint8;
}) -> (struct {
new_state GameState;
}) error MoveError;
};
FIDL 工具鍊會為 std::result::Result<GameState, MoveError>
產生公開 TicTacToeMakeMoveResult
型別別名。這個方法的其他繫結程式碼會產生,就好像它具有 TicTacToeMakeMoveResult
類型的單一回應參數 result
一樣。成功結果所使用的類型會遵循參數類型轉換規則。
不明的互動處理
伺服器端
當通訊協定宣告為 open
或 ajar
時,系統產生的 request enum 將會包含額外的變化版本 _UnknownMethod
,其中包含以下欄位:
#[non_exhausitve]
_UnknownMethod {
/// Ordinal of the method that was called.
ordinal: u64,
/// Control handle for the protocol.
control_handle: TicTacToeControlHandle,
/// Enum indicating whether the method is a one-way method or a two way
/// method. This field only exists if the protocol is open.
method_type: fidl::MethodType,
}
MethodType
是列舉,其中包含兩個單位變化版本 OneWay
和 TwoWay
,可指出呼叫哪種方法。
每當伺服器收到彈性不明事件時,要求串流就會發出此要求列舉的變化版本。
用戶端
用戶端無法判斷伺服器是否知道 flexible
單向方法。對於 flexible
雙向方法,如果伺服器不認識該方法,用戶端會收到 Err
結果,其值為 fidl::Error::UnsupportedMethod
。UnsupportedMethod
錯誤只會發生在彈性雙向方法中。
除了可能會發生 UnsupportedMethod
錯誤之外,在用戶端上,strict
和 flexible
方法之間沒有任何 API 差異。
針對 open
和 ajar
通訊協定,系統會產生額外的 _UnknownEvent
變化版本,其中包含以下欄位:event enum
#[non_exhaustive]
_UnknownEvent {
/// Ordinal of the event that was sent.
ordinal: u64,
}
每當用戶端收到不明事件時,用戶端事件串流就會發出這個事件列舉的變化版本。
通訊協定組合
FIDL 沒有繼承概念,並會為所有組合通訊協定產生完整程式碼,如上所述。換句話說,系統會為下列項目產生程式碼:
protocol A {
Foo();
};
protocol B {
compose A;
Bar();
};
與下列程式碼相同:
protocol A {
Foo();
};
protocol B {
Foo();
Bar();
};
通訊協定和方法屬性
新舊混搭風
@transitional
屬性只會影響 ProxyInterface
特徵,後者有時會用於測試程式碼。針對非測試程式碼,您可以讓要求處理常規暫時在 Request
處理常規中使用萬用配對分支,藉此在伺服器端轉換通訊協定。產生的 Proxy 一律會實作所有方法,因此用戶端程式碼不需要進行軟轉換。
對於標記為 @transitional
屬性的方法,非同步用戶端的 ProxyInterface
特徵會提供呼叫 unimplemented!()
的預設實作項目。如先前所述,這不會影響 Proxy
類型,因為該類型一律會實作所有特徵的方法。不過,如果在用戶端單元測試中使用 ProxyInterface
特徵來模擬 Proxy,這項功能就會有所助益。
可供偵測
如果是標記為 @discoverable
屬性的通訊協定,標記類型會另外實作 fidl::endpoints::DiscoverableProtocolMarker
特徵。這會提供 PROTOCOL_NAME
相關聯的常數。
明確的編碼和解碼
傳送 FIDL 訊息時,系統會自動對訊息進行編碼,接收訊息時則會解碼。您也可以明確地進行編碼和解碼,例如將 Fidl 資料儲存在檔案中。根據 RFC-0120:使用獨立的 FIDL 線路格式,繫結會提供 持久性 API 和 獨立 API。
保留
建議您使用 persist
和 unpersist
,明確地進行編碼和解碼。這適用於非資源結構體、表格和聯合體。
例如,您可以保留 Color
結構體:
let original_value = fex::Color { id: 0, name: "red".to_string() };
let bytes = fidl::persist(&original_value)?;
然後稍後取消持久化:
let decoded_value = fidl::unpersist(&bytes)?;
assert_eq!(original_value, decoded_value);
一般版 UI
如果進階用途不需使用持久性 API,您可以使用獨立的編碼和解碼 API。這適用於所有結構體、表格和聯集。這裡有兩組函式:一組是用於值類型,另一組是用於資源類型。
舉例來說,由於 JsonValue
聯集是值類型,因此我們會使用 standalone_encode_value
對其進行編碼:
let original_value = fex::JsonValue::StringValue("hello".to_string());
let (bytes, wire_metadata) = fidl::standalone_encode_value(&original_value)?;
這會傳回位元組向量和不透明物件,用於儲存線路格式中繼資料。如要解碼,請將兩個值傳遞至 standalone_decode_value
:
let decoded_value = fidl::standalone_decode_value(&bytes, &wire_metadata)?;
assert_eq!(original_value, decoded_value);
舉例來說,請考慮結構體 EventStruct
:
type EventStruct = resource struct {
event zx.Handle:<EVENT, optional>;
};
由於這是資源類型,因此我們會使用 standalone_encode_resource
進行編碼:
let original_value = fex::EventStruct { event: Some(fidl::Event::create()) };
let (bytes, handle_dispositions, wire_metadata) =
fidl::standalone_encode_resource(original_value)?;
除了位元組和線路格式中繼資料之外,這也會傳回 HandleDisposition
的向量。如要解碼,請將句柄指示轉換為 HandleInfo
,然後將所有三個值傳遞至 standalone_decode_resource
:
let mut handle_infos = fidl::convert_handle_dispositions_to_infos(handle_dispositions)?;
let decoded_value: fex::EventStruct =
fidl::standalone_decode_resource(&bytes, &mut handle_infos, &wire_metadata)?;
assert!(decoded_value.event.is_some());
附錄 A:衍生特徵
"Debug",
"Copy",
"Clone",
"Default",
"Eq",
"PartialEq",
"Ord",
"PartialOrd",
"Hash",
附錄 B:填滿衍生
您可以在 fidlgen_rust 中查看特徵衍生規則的計算方式:
// Calculates what traits should be derived for each output type,
// filling in all `*derives` in the IR.
func (c *compiler) fillDerives(ir *Root) {