在開發程式的時候,我們很常需要產生出有獨立名稱,且為連續或是有規律的數值,用來當作介面的參數數值。舉例來說,有一個函數擁有10種工作模式,可以透過該函數的第一個參數來傳入數值0~9來決定要使用哪一種模式,為了方便輸入,且為了確保輸入的數值是在0~9,我們通常會使用一種特殊結構作為這個參數的型別,來代入數值0~9。如果程式語言支援列舉(enum),這個功能通常會直接使用列舉來實現。但是Rust程式語言的列舉有個小缺點,那就是它不方便直接利用列舉變體的「序數」(ordinal),也就是那個變體在該列舉中被定義出來的順序,作為程式邏輯的應用。另外,如果要透過「序數」來取得對應的列舉變體,並沒有內建安全的作法。



內建取得列舉變體「序數」的作法

如果要得到某列舉變體的序數,必須要使用「as」關鍵字,直接將列舉實體轉型。程式如下:

但如果是列舉實體的參考,則無法使用「as」關鍵字來進行轉型。舉例來說:

以上程式,第12行會編譯失敗。需將程式修改成:

所以說這個方式並不太好用。

Enum Ordinalize

「Enum Ordinalize」是筆者開發的套件,可以讓新建立出來的列舉擁有「ordinal」、「from_ordinal」和「from_ordinal_unsafe」方法,列舉的序數的型別均為isize。

Crates.io

https://crates.io/crates/enum-ordinalize

Cargo.toml

enum-ordinalize = "*"

巨集的使用

Enum Ordinalize提供的「create_ordinalized_enum」巨集可以快速產生出擁有「ordinal」、「from_ordinal」和「from_ordinal_unsafe」方法且實作了「Debug」、「PartialEq」、「Clone」、「Eq」和「Hash」特性的列舉。

例如:

「from_ordinal」和「from_ordinal_unsafe」方法的差異在於,「from_ordinal_unsafe」方法的轉換方式是直接使用相同的記憶體空間的值,效能較好,但程式設計師必須十分確定傳進去的值是可以進行正確轉換的,否則程式會直接panic。

如果要將建立出來的列舉設成「公開的」,可以在列舉名稱前加上「pub」關鍵字。例如:

另外,如果想自訂序數的值,可以直接用「變體名稱 = 值」的語法來定義列舉。例如:

這邊要注意的是,自訂的序數值也只能是isize型別。