在開發程式的時候我們時常會需要判斷某個字串的開頭或結尾是否符合某個字串,例如判斷網址是否以http
或是https
開頭時,或是判斷檔案名稱是否以.jpg
或是.png
結尾時。然而在上述提到的例子中,通訊協定或是檔案副檔名都是可忽略大小寫的,Rust程式語言雖然有提供eq_ignore_ascii_case
方法,卻沒有提供starts_with_ignore_ascii_case
和ends_with_ignore_ascii_case
等方法,在判斷上述例子時需要程式設計師自行先把字串做轉大寫或是轉小寫的動作才能進行判斷。
如以下程式,可以判斷一個檔案路徑的副檔名是否為png。
if path.to_lowercase().ends_with(".png") {
...
}
以上程式,因為我們不知道path
的副檔名是png
、PNG
,還是PnG
,因此只好先將其透過to_lowercase
方法來轉成小寫,如此一來只要用ends_with
來判斷它是否以.png
結尾就好。
然而,對字串使用to_lowercase
方法,會另外產生新的字串出來,這會讓程式記憶體用得更多,程式效能也會變得比較不好。
所以,比較好的作法是,先取得path
的副檔名部份的字串切片,再利用Rust程式語言的字串內建的eq_ignore_ascii_case
方法,來做判斷。程式改寫如下:
if path[(path.len() - ".png".len())..].eq_ignore_ascii_case(".png") {
...
}
這樣寫起來有點麻煩,而且還有可能因path
本身沒有到達.png
的長度,而導致程式發生panic,因此在將path
轉成更小範圍的字串切片前還需進行長度的檢查。
str Utils
「str Utils」是筆者開發的套件,提供了一些特性,可以擴充有實作AsRef<[u8]>
或是AsRef<str>
特性的型別,使它們擁有更多的字串相關的方法。
Crates.io
Cargo.toml
使用方法
文章一開始舉的例子,可以用EndsWithIgnoreAsciiCase
特性改寫成以下程式:
use str_utils::EndsWithIgnoreAsciiCase;
...
if path.ends_with_ignore_ascii_case(".png") {
...
}
另外,由於我們可以確定輸入至ends_with_ignore_ascii_case
方法的字串一定是小寫,所以可以改用ends_with_ignore_ascii_case_with_lowercase
方法以獲得更好的效能。
use str_utils::EndsWithIgnoreAsciiCase;
...
if path.ends_with_ignore_ascii_case_with_lowercase(".png") {
...
}
當然這個套件的功能不只這些,再舉幾個用法:
use str_utils::*;
assert_eq!(true, "foobar".starts_with_ignore_ascii_case("FoO"));
assert_eq!(Some(1), "photo.jpg".ends_with_ignore_ascii_case_multiple(&[".png", ".jpg", ".gif"]));
assert_eq!(true, "http".eq_ignore_ascii_case_with_uppercase("HTTP")); // faster than `eq_ignore_ascii_case`