在開發程式的時候常常會需要處理檔案路徑或是URL網址的串接問題,如果字串是從使用者端輸入的,由於不同使用者的習慣不同,可能有人習慣在檔案目錄路徑或是網址前面後面多加斜線,也可能有人習慣不加。如果程式是設計成要用某個使用者輸入的字串當作前綴,去串接其它的字串來組成檔案路徑或是網址的話,那麼前綴是不是以斜線結尾的影響就很大了。例如使用者輸入了「path/to/folder/」這樣的檔案目錄路徑,然後程式要串在其後的字串為「/file」,串起來之後的路徑就變成「path/to/folder//file」,這就可能會是一個不合法的路徑。



因為使用者習慣不同,所以我們必須要做其它的處理。例如以下程式,可以去除輸入的字串之最後面的斜線,但是如果它原本就只是一個斜線的話就不再去除:

let length = s.len();

if length > 1 && s.ends_with('/') {
    return &s[..length - 1];
} else {
    return s;
}

程式非常簡單,但也是因為如此,如果每次都要在新的程式專案中,寫這樣類似或是一樣的程式碼來處理斜線,那真的很無聊。

Slash Formatter

「Slash Formatter」是筆者開發的套件,提供多種函數來處理斜線和反斜線的字串串接。

Crates.io

https://crates.io/crates/slash-formatter

Cargo.toml

slash-formatter = "*"

使用方法

「slash-formatter」這個crate,提供了數十種的函數,主要有「add_start_slash」、「add_end_slash」、「delete_start_slash」、「delete_end_slash」、「concat_with_slash」這五大類,且每一類皆有「slash」(斜線)、「backslash」(反斜線)和「file_separator」(根據作業系統來決定用斜線或是反斜線)的分別。其中再依照擁有權來優化,又可以另分出「owned」(取得擁有權來處理,例如「add_start_slash_owned」)和「mut」(取得可變參考來處理,例如「add_start_slash_mut」)兩種函數。所以每一類都有9個函數,五大類合起來共45個函數

舉例來說,如果要以斜線串接兩個字串,程式如下:

extern crate slash_formatter;

assert_eq!("path/to", slash_formatter::concat_with_slash("path", "to/"));

extern crate slash_formatter;

let mut s = String::from("path");

slash_formatter::concat_with_slash_mut(&mut s, "to/");

assert_eq!("path/to", s);

extern crate slash_formatter;

let s = String::from("path");

let s = slash_formatter::concat_with_slash_owned(s, "to/");

assert_eq!("path/to", s);

如果要以反斜線串接兩個字串,程式如下:

extern crate slash_formatter;

assert_eq!(r"path\to", slash_formatter::concat_with_backslash("path", r"to\"));

extern crate slash_formatter;

let mut s = String::from("path");

slash_formatter::concat_with_backslash_mut(&mut s, "to\");

assert_eq!("path\to", s);

extern crate slash_formatter;

let s = String::from("path");

let s = slash_formatter::concat_with_backslash_owned(s, "to\");

assert_eq!("path\to", s);

如果要根據運行的作業系統環境來決定要使用斜線還是反斜線來串接兩個字串的話,程式如下:

extern crate slash_formatter;

assert_eq!(r"path\to", slash_formatter::concat_with_file_separator("path", r"to\"));

extern crate slash_formatter;

let mut s = String::from("path");

slash_formatter::concat_with_file_separator_mut(&mut s, "to/");

assert_eq!("path/to", s);

extern crate slash_formatter;

let s = String::from("path");

let s = slash_formatter::concat_with_file_separator_owned(s, "to/");

assert_eq!("path/to", s);

當然,如果您只是純粹想串接出能用用在目前程式執行的作業系統上的檔案路徑,可以直接使用Rust標準函式庫提供的「std::path」模組來處理路徑串接問題。

巨集用法

「Slash Formatter」在2.2.0版本之後針對斜線的串接加入了與「concat_with_slash」、「concat_with_slash_mut」、「concat_with_backslash」、「concat_with_backslash_mut」、「concat_with_file_separator」、「concat_with_file_separator_mut」函數同名的巨集,支援多個字串的串接。巨集省略了「owned」版本,是因為已經跟原始的版本做在一起了!

用法如下:

#[macro_use] extern crate slash_formatter;

assert_eq!("path/to/file", concat_with_slash!("path", "to/", "/file/"));

let s = String::from("path");

let s = concat_with_slash!(s, "to/", "/file/");

assert_eq!("path/to/file", s);

#[macro_use] extern crate slash_formatter;

let mut s = String::from("path");

concat_with_slash_mut!(&mut s, "to/", "/file/");

assert_eq!("path/to/file", s);