你需要知道的 32 個 Rust 庫 - 3

11,Rayon

Rayon 庫使得在 Rust 中更容易使用並行性,它適用於將順序迭代器轉換爲並行迭代器,並保證沒有數據競爭。並行迭代器在運行時調整其行爲以獲得最大性能。

use rayon::prelude::*;
fn sum_of_squares(input: &[i32]) -> i32 {
    input
         .par_iter() // <-- just change that!
         .map(|&i| i * i)
         .sum()
}

在上面的示例中,只需將 iter() 更改爲 par_iter(),就可以將順序迭代器轉換爲並行迭代器。

12,Crossbeam

Crossbeam crate 爲併發編程提供了一組工具:原子、數據結構、內存管理、線程同步等等。

例如,與 std channels 相比,Crossbeam 中 channels 的實現性能更高,並且允許多個生產者和多個消費者 (multi-producer multi-consumer),而不像 std channels 只允許單個消費者 (multi-producer single-consumer)。

13,async_trait

目前,Rust 在語言語法級別上不支持異步 trait,而 async_trait 允許定義異步 trait。

use async_trait::async_trait;

#[async_trait]
trait Advertisement {
    async fn run(&self);
}

struct Modal;

#[async_trait]
impl Advertisement for Modal {
    async fn run(&self) {
        self.render_fullscreen().await;
        for _ in 0..4u16 {
            remind_user_to_join_mailing_list().await;
        }
        self.hide_for_now().await;
    }
}

14,fs-err

fs-err crate 封裝了 std::fs 中的錯誤信息,使其具有人類可讀性。

如果你使用過 std::fs 中的函數 (如 read_to_string 或 write),你可能已經注意到,在出現錯誤的情況下,錯誤消息不是很有用:

let content = File::open("file-not-exist.txt")?;
let config = File::open("config-not-exist.txt")?;

// error message would be:
// The system cannot find the file specified. (os error 2)

使用 fs-err crate,我們可以獲得更詳細的錯誤消息,例如哪個文件不存在:

failed to open file `config-not-exist.txt`
    caused by: The system cannot find the file specified. (os error 2)

15,Tempfile

Tempfile crate 提供了一個用於創建臨時文件和目錄的 API。

// Write
let mut tmpfile: File = tempfile::tempfile().unwrap();
write!(tmpfile, "Hello World!").unwrap();

// Seek to start
tmpfile.seek(SeekFrom::Start(0)).unwrap();

// Read
let mut buf = String::new();
tmpfile.read_to_string(&mut buf).unwrap();
assert_eq!("Hello World!", buf);

16,Bincode

Bincode crate 提供了字節數組結構的編碼和解碼。它使用一種緊湊的數據格式,適合存儲在磁盤上,也適合在具有不同處理器架構的系統之間交換數據。

use anyhow::Result;
use serde::{de::DeserializeOwned, Deserialize, Serialize};

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Entity {
    number: i8,
    name: String,
}

fn check<T>(value: &T, expected_size: usize)
where
    T: Serialize + DeserializeOwned + PartialEq + std::fmt::Debug,
{
    let encoded: Vec<u8> = bincode::serialize(&value).unwrap();
    assert_eq!(encoded.len(), expected_size);

    let decoded: T = bincode::deserialize(&encoded[..]).unwrap();
    assert_eq!(value, &decoded);
}

#[test]
fn test() -> Result<(){
    let first_size = 9; // i8 + u64 for string length
    check(&Entity {number: 1, name: "".to_owned()}, first_size);
    let second_size = 15; // i8 + u64 for string length + 6 bytes of string
    check(&Entity {number: 2, name: "string".to_owned()}, second_size);
    Ok(())
}

17,Maplit

Maplit crate 用於生成容器類型的宏,對應於標準庫中的容器類型。這在很大程度上是個人偏好的問題,因爲容器已經有 from 和 from_iter 方法。

let a = btreemap! {
    "a" => vec![1, 2, 3],
    "b" => vec![4, 5, 6],
    "c" => vec![7, 8, 9],
};
// vs
let b = BTreeMap::from([
    ("a", vec![1, 2, 3]),
    ("b", vec![4, 5, 6]),
    ("c", vec![7, 8, 9]),
]);

18,Indexmap

保留元素插入順序的有序哈希映射。這意味着遍歷哈希映射元素的順序將元素的插入順序相同。這個順序一直保持到調用 remove 方法爲止。

哈希映射支持按鍵和數字索引 (類似於數組) 搜索元素,並支持對元素進行快速迭代。

所有這些屬性都源於這樣一個事實,即它存儲了一個鍵值對向量和一個將鍵的哈希映射到向量中的索引的哈希表。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/I1-7U0ACosnxvtaplKYXIQ