開發程式的時候,常會需要讓程式能與使用者或其它程式互動,透過文字介面、圖形介面或是通訊協定標準,從外部取得資料來進行更進一步的處理。尤其是當使用者在使用我們的程式時,由於我們沒有辦法限制他們輸入的資料一定要符合程式設計的格式,程式很可能就會因錯誤的輸入而造成錯誤的輸出,甚至對整個系統的安全性造成威脅。所以通常我們在處理外部進來的資料時,會先檢查它們的格式後再進行處理。



Validators

「Validators」是筆者開發的套件,提供了統一的用法來驗證多種不同的資料格式。比如要驗證的資料格式為「XXX」(XXX可以是網址、網域、電子郵件、Base64字串等等),「Validators」套件就會提供這個「XXX」格式的「驗證器」(命名為「XXXValidator」),用來設定這個格式允許或必須啟用的項目,像是網址需不需要包含通訊協定和連接埠等等。這些設定項目都是「ValidatorOption」列舉的值,有「Must」、「Allow」、「NotAllow」三個變體,分別表示該項目是否「必要」、「允許」還是「不允許」。也就是說,就算都是符合「XXX」格式的資料,可能會因「XXXValidator」的選項設定不同,而保有細節上的差異。

也是因為有這些細節上的差異,每種「XXX」格式,也有其包裝格式(Wrappers)。例如「Domain」(網域)這個格式,它的驗證器「DomainValidator」,可以設定這個網域資料能不能包含連接埠,和其網域名稱能不能是本地端名稱「localhost」,所以「Domain」格式就擁有「DomainLocalhostableAllowPort」、「DomainLocalhostableWithPort」、「DomainLocalhostableWithoutPort」、「DomainUnlocalhostableAllowPort」、「DomainUnlocalhostableWithPort」、「DomainUnlocalhostableWithoutPort」這六種不同的包裝格式。包裝格式可以直接被用來檢查輸入資料,並建立出可序列化與反序列化的資料模型。

Crates.io

https://crates.io/crates/validators

Cargo.toml

validators = "*"

使用方法

「validators」這個crate下,以不同的模組來區分不同的資料格式,例如「Domain」(網域)這個格式和其相關的驗證器和包裝格式,就是屬於「domain」模組。用法如下:

自定義的格式

「Validators」套件當然不可能包山包海,把全部的資料格式都包成模組。會包成模組的主要還是如網址、網域、電子郵件、Base64字串等等常見的資料格式。但「Validators」套件也不是不能處理其它不在模組內的資料格式,只是這些格式必須由各位程式設計師來定義其反序列化的方式了!針對可轉為字串、數值和Vec結構體(也就是陣列)的資料,「Validators」套件提供了一些方便的巨集,可以快速產生出他們的包裝格式。

像是要建立出一個只接受「Hi」或「Hello」字串的包裝格式,我們可以利用「validated_customized_regex_string」巨集,搭配正規表達式「^(Hi|Hello)$」,撰寫出以下程式:

以上程式中,我們實作出一個「Greet」結構體,並限制這個結構體只能表示「Hi」或「Hello」字串。

「validated_customized_regex_string」巨集雖然很方便,但由於程式要使用正規表達式時,需要先耗費額外的硬體資源來編譯它,因此在比較頻繁使用狀況下,「validated_customized_regex_string」巨集所實作出來的結構體之效能可能會不盡理想。此時我們可以考慮用全域靜態變數的方式,重複使用同一個已編譯好的正規表達式實體。程式可改寫如下:

將「validated_customized_regex_string」巨集的第二個參數,從正規表達式,改為「ref」關鍵字再加上靜態變數的名稱,就可以重複使用該靜態變數所儲存的正規表達式實體了!

如果要讓我們自定義的包裝格式變成公開的結構體,只需要在名稱前加上「pub」關鍵字即可,程式如下:

至於數值資料,若我們要求資料只能夠是0到100(包含0和100)的u8數值,來表示滿分為100的分數。可以利用「validated_customized_ranged_number」巨集寫出以下程式:

如果是陣列資料,可以使用「validated_customized_ranged_length_vec」巨集再搭配其它的包裝格式,來快速實作出有限制數量範圍的陣列資料格式。如下:

如果是集合資料(不重複的資料),可以使用「validated_customized_ranged_length_hash_set」巨集再搭配其它的包裝格式,來快速實作出有限制數量範圍的HashSet資料格式。如下:

上面所提到的只是常用巨集的部份,另外還有其它比較低階的巨集,如果有需要的話就照著套件的文件來用吧!

Rocket框架支援

Rocket是Rust的一個Web框架,「Validators」套件所有的包裝格式接有實作Rocket的「FromFormValue」和「FromParam」特性。如果要啟用「Validators」套件Rocket框架支援,只需要開啟「rocketly」特色,「Cargo.toml」設定檔的寫法如下:

開啟「rocketly」特色後,「Validators」套件的包裝格式就是可以直接當作資料模型,用在Rocket框架中了!

Serde框架支援

Serde是Rust的一個資料序列化和反序列化的框架,「Validators」套件所有的包裝格式接有實作Serde的「Serialize」和「Deserialize」特性。如果要啟用「Validators」套件Serde框架支援,只需要開啟「serdely」特色,「Cargo.toml」設定檔的寫法如下:

開啟「serdely」特色後,「Validators」套件的包裝格式就是可以直接用於Serde框架中,在不同格式間進行序列化與反序列化了!