正在產生 FIDL Rust Crate
您可以透過下列兩種方式從 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 Rust Crate 中的部分方法和常數是由實作 FIDL 執行階段 Crate 提供的特徵提供。如要存取這些特徵,您必須匯入對應的特徵。最簡單的做法是從 Prelude 模組一次匯入所有資源:
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 工具鍊如何將 Rust 中的 FIDL 類型轉換為原生類型。這些類型可以顯示為匯總類型的成員,或顯示為通訊協定方法的參數。
內建類型
在下表中,如果您同時指定「擁有」和「借用」變體,則「擁有」類型是指出現在匯總類型中的類型 (例如結構欄位或向量元素的類型),而「借用」類型則是指從用戶端的角度來看,將其做為通訊協定方法參數或元組參數使用的類型。為了利用 Rust 擁有權模型,擁有和借用的區別存在。發出包含 T
類型參數的要求時,經 Proxy 的函式呼叫不需要取得 T
的擁有權,因此 FIDL 工具鍊需要產生 T
的借用版本。借用的版本通常使用 &mut
,因為類型 T
可能包含控點,在這種情況下,FIDL 在編碼時會將控制代碼歸零,以修改輸入內容。如果使用 &mut
取代擁有權,呼叫端在不含控制代碼的情況下,可允許呼叫端重複使用輸入值。
FIDL 類型 | 鐵鏽類型 |
---|---|
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
。struct 和 unions 可分為必要或選用,可在自有的結構定義或借用情境中使用,這代表有四種可能的 Rust 類型。特定 struct T
或 union T
的類型如下:
已擁有 | 借用 | |
---|---|---|
必要 | 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
:傳回原始值,其中僅包含此位元值中的未知成員。如果是 strict 位元,則會標示為#[deprecated]
且一律傳回 0。has_unknown_bits(&self) -> bool
:傳回這個值是否包含任何不明位元。如果是 strict 位元,會標示#[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())
}
}
不明巨集的運作方式與 _
模式相同,但可以設為展開廣泛比對。如要找出遺漏的案件,這項資訊就能派上用場。
結構
使用 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: reserved;
2: int_value int32;
3: 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
。
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 中的不明資料」。
Strict 聯集在解碼未知的變數時失敗。彈性聯集在解碼未知的變數時成功,但重新編碼時會失敗。
桌子
使用 table 定義:
type User = table {
1: reserved;
2: age uint8;
3: 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
:實作這個通訊協定的伺服器必須處理相關聯的要求串流。在這個範例中,這是由 FIDL 產生的TicTacToeRequestStream
。
此外,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
:取得 Proxy 基礎管道的參照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>
:啟動和忘記通訊協定方法的 Proxy 方法。它會將要求參數做為引數,並傳回空白結果。make_move(&self, mut row: u8, mut col: u8) -> Self::MakeMoveResponseFut
:雙向的 Proxy 方法。它會將要求參數做為引數,並傳回回應的Future
。
Rust 教學課程中會提供設定非同步 Proxy 的範例。
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())
}
}
同步
對於 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::Time) -> Result<(bool, Option<Box<GameState>>), fidl::Error>
:雙向方法的 Proxy 方法。它會將要求參數做為引數,後面接有期限參數,此參數用於指定方法呼叫等待回應的時間長度 (或zx::Time::INFINITE
無限期封鎖)。這個方法會傳回回應參數的Result
。wait_for_event(&self, deadline: zx::Time) -> Result<TicTacToeEvent, fidl::Error>
:在收到事件或期限到期前進行封鎖 (使用zx::Time::INFINITE
無限期封鎖)。它會傳回TicTacToeEvent
列舉的Result
。
Rust 教學課程中提供了設定同步 Proxy 的範例。
伺服器
通訊協定要求串流
為了表示對伺服器的傳入要求串流,FIDL 工具鍊會產生實作 futures::Stream<Item
= Result<TicTacToeRequest, fidl::Error>>
和 fidl::endpoints::RequestStream
的 TicTacToeRequestStream
類型。每個通訊協定都有對應的要求串流類型。
要求列舉
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
時,產生的要求列舉會有一個名為 _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
雙向方法,如果伺服器不知道該方法,用戶端會收到值為 fidl::Error::UnsupportedMethod
的 Err
結果。UnsupportedMethod
錯誤僅適用於彈性雙向方法。
除了可能收到 UnsupportedMethod
錯誤以外,用戶端上的 strict
和 flexible
方法沒有 API 差異。
如果是 open
和 ajar
通訊協定,產生的事件列舉會有一個名為 _UnknownEvent
的額外變數,其中包含以下欄位:
#[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
類型,因為其一律會實作所有 trait 的方法。不過,如果在用戶端單元測試中使用 ProxyInterface
特徵,則有助於進行軟轉換。
可供偵測
針對加上 @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) {