32 Rust crates you better know about
Tags: rust, crate, derive, macro
Published: 2023-05-05 16:23:31

In this article, I want to share information about crates for the Rust language that you may not know about. Most of them allow you to write less boilerplate code or improve code readability. This article will be useful for developers of all levels who write in Rust.

Share in the comments crates that may be useful to other developers.

In this article, a crate refers to a library that can be used as a dependency in your project.

I did not copy the entire documentation for each crate, so if you are interested in a crate, I recommend checking it out on [crates.io](crates.io) or [docs.rs](docs.rs).

Also, I did not give examples of well-known crates such as `serde`, `anyhow`, `itertools`, and others.

## Preface

You may have noticed that many projects written in Rust have a large number of primary and secondary dependencies. In my opinion, there is nothing wrong with this, and here's why. Rust has high requirements for backward compatibility of the standard library. Therefore, much of the functionality is provided in the form of third-party dependencies, maintained by the community, rather than by the language creators. At the same time, Rust implemented good dependency management in the form of Cargo at an early stage, which makes adding dependencies trivial. Together, this allows Rust crates to evolve faster, have less legacy code, and gives users the ability to choose between different implementation approaches, rather than relying solely on what the language creators included in the standard library. The above allows writing Rust crates in the Unix way, where each library does exactly one thing and does it well.

The "batteries included" approach adopted, for example, in Python worked well in the 1990s when software distribution was not as easy. Now it leads to [clean-up initiatives](https://peps.python.org/pep-0594) of the Python standard library.

<!--
Basically because Rust realised a good dependency management early on and decided that having them in independent dependencies has some clear advantages.

Cargo packages can evolve faster, leave less legacy garbarage and between compeating approaches the one that most users prefer is chosen, not what some designer or commitee things is the better solution.

Having everything including the kitchen sink in the stdlib leads to problems in the future e.g. https://peps.python.org/pep-0594/ things like this go against Rusts heavy focus on backwards compatibility.

dev here ... python has way too many things in its standard library, no contemporary language would do that nowadays. So many batteries included made sense at a time when software distribution wasn't so easy, and the consequence is that now there is a huge tech debt - actually plenty of python builtins aren't recommended at all.

I'm not that familiar with Python only using it occasionally for some scripts and stuff but pretty much every time I want to do something (in Python) and google how to do that, people are posting examples using 3rd party packages instead of the stdlib so I'm sure there's a reason for that.
-->

## tap

A crate that allows converting a chain of function calls from prefix notation to postfix notation. This form allows you to write more readable code.

It is easiest to explain with examples. For example, a chain of calls like this:

```rs
let val = last(
  third(
    second(first(original_value), another_arg)
  ),
  another_arg,
);
```
Can be rewritten as:
```rs
let val = original_value
  .pipe(first)
  .pipe(|v| second(v, another_arg))
  .pipe(third)
  .pipe(|v| last(v, another_arg));
```

Or, suppose you want to sort an array "in place" using the `sort()` method, which will require making the variable mutable first, and then redefining the variable to make it immutable again:
```rs
let mut collection = stream().collect::<Vec<_>>();
collection.sort();
// potential error site: inserting other mutations here
let collection = collection; // now immutable
```
The `.tap_mut` method comes to the rescue, which passes the value of the variable by mutable reference to the closure:
```rs
let collection = stream.collect::<Vec<_>>().tap_mut(|v| v.sort());
```
Accordingly, the variable `collection` can be defined only once and be immutable from the start.

These methods do not affect the performance of the code, since at the compilation stage, these calls are optimized and the resulting code is just as performant as the naive version.

In my opinion, in both examples, the code became more readable because we got rid of unnecessary variable declarations and rewrote the function calls in a chain-like way, which allows you to read the code without jumping your eyes around the lines.

These are not all the useful methods provided by this crate. For example, it contains `tap_x_dbg` methods, which work in debug mode and are removed in release mode. There are also methods for converting between types that implement the `Into` trait.

I recommend to check out the documentation of this crate.

## strum

The crate helps to get rid of boilerplate code when working with enums in Rust. The functionality is achieved through derive-type macros.

For example:
1. `strum::Display` - implements `std::fmt::Display` for an enum and therefore the `to_string() -> String` method.
2. `strum::AsRefStr` - implements `AsRef<&static str>`. Therefore, it does not require memory allocation as in the case of using `to_string()`.
3. `strum::IntoStaticStr` - implements `From<MyEnum> for &'static str`. Works similarly to the previous option.
4. `strum::EnumString` - implements `std::str::FromStr` and `std::convert::TryFrom<&str>`, allowing you to convert strings into enum instances.
5. `strum::EnumCount` - adds the constant `COUNT: usize`, which contains the number of enum variants.
6. `strum::EnumIter` - implements an iterator over the enum variants. The data inside the variants will be set to `Default::default()`.

And even more. I recommend taking a look at the [documentation of this crate](https://docs.rs/strum/latest).

An example of using the above macros:
```rs
#[derive(
    Debug,
    PartialEq,
    strum::Display,
    strum::IntoStaticStr,
    strum::AsRefStr,
    strum::EnumString,
    strum::EnumCount,
    strum::EnumIter,
)]
enum Color {
    Red,
    Blue(usize),
    Green { range: usize },
}

// convertions to String and &'static str
assert_eq!(Color::Blue(2).to_string(), "Blue");
assert_eq!(Color::Green { range: 5 }.as_ref(), "Green");
assert_eq!(<&str>::from(Color::Red), "Red");

assert_eq!(Color::Red, Color::from_str("Red").unwrap());
assert_eq!(Color::COUNT, 3);
assert_eq!(
    Color::iter().collect::<Vec<_>>(),
    vec![Color::Red, Color::Blue(0), Color::Green { range: 0 }]
);
```

Additionally, different macros of this crate support behavior customization. For example, it is possible to change the string into which an enum instance will be converted using the attribute `#[strum(serialize = "redred")]`.

## derive_more

The NewType pattern is pretty common in Rust. Sometimes you need wrap third-party library types in our own structure:
```rs
pub struct NonEmptyVec(Vec<i32>);
```

One of the examples of using this pattern is to maintain invariants. For our structure, we can define a constructor function that checks that the internal vector is never empty:
```rs
impl NonEmptyVec {
    pub fn new(numbers: Vec<i32>) -> Result<Self> {
        if numbers.is_empty() {
            bail!("expected non empty vector of integers")
        } else {
            Ok(Self(numbers))
        }
    }
}
```

Therefore, the structure can only be created through a constructor that checks the required invariant. The downside of this approach is that our wrapper structure `NonEmptyVec` does not inherit the implementation of traits from the internal type.

For example, what if we want to pass the structure to a function that takes `IntoIterator` as input? This code will not compile:
```rs
fn collector(iter: impl IntoIterator<Item = i32>) -> Vec<i32> {
    iter.into_iter().collect()
}

#[test]
fn non_emtpy_vec() -> Result<()> {
    let non_empty = NonEmptyVec::new(vec![1, 2, 3])?;
    assert_eq!(collector(non_empty), vec![1, 2, 3]);
    Ok(())
}
```

We can write our own implementation:
```rs
impl IntoIterator for NonEmptyVec {
    type Item = <Vec<i32> as IntoIterator>::Item;
    type IntoIter = <Vec<i32> as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        <Vec<i32> as IntoIterator>::into_iter(self.0)
    }
}
```

But essentially, this is boilerplate code because it duplicates the existing implementation of the trait of the internal type. This crate can help eliminate such code. We simply add the use of the derive macros for our wrapper structure:
```rs
#[derive(derive_more::AsRef, derive_more::Deref, derive_more::IntoIterator, derive_more::Index)]
pub struct NonEmptyVec(Vec<i32>);
```

And check that this works:
```rs
fn collector(iter: impl IntoIterator<Item = i32>) -> Vec<i32> {
    iter.into_iter().collect()
}

#[test]
fn non_emtpy_vec() -> Result<()> {
    assert!(NonEmptyVec::new(vec![]).is_err());

    let non_empty = NonEmptyVec::new(vec![1, 2, 3])?;
    assert_eq!(non_empty.as_ref(), &[1, 2, 3]);
    assert_eq!(non_empty.deref(), &[1, 2, 3]);
    assert_eq!(non_empty[1], 2);
    assert_eq!(collector(non_empty), vec![1, 2, 3]);
    Ok(())
}
```

As you see, we automatically restored the implementation of several useful traits.

This crate contains macros for generating conversion traits (`From`, `IntoIterator`, `AsRef`, etc), formatting traits (`Display`-like), operator traits (`Add`, `Index`, etc), useful methods (`Constructor`, `Unwrap`, etc).

## derive_builder

One of the popular patterns in Rust is the builder pattern [[1](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html), [2](https://rust-unofficial.github.io/patterns/patterns/creational/builder.html)]. This pattern is convenient when you need to create a complex structure with many fields.

For example, let's say we have several functions that perform some complex work and return a result of `Calculation` - a structure with many optional fields - and then we want to test the functions in a unit test:
```rs
#[derive(Debug, Eq, PartialEq)]
struct Calculation {
    a: Option<i32>,
    b: Option<i32>,
    c: Option<i32>,
    d: Option<i32>,
    // ... can be more optional fields
}

fn qwe() -> Calculation {
    // does complex calculation
    Calculation {
        a: Some(1),
        b: None,
        c: None,
        d: None,
    }
}

fn asd() -> Calculation {
    // does complex calculation
    Calculation {
        a: Some(6),
        b: None,
        c: None,
        d: Some(7),
    }
}

fn zxc() -> Calculation {
    // does complex calculation
    Calculation {
        a: None,
        b: Some(2),
        c: Some(3),
        d: None,
    }
}

#[test]
fn test() -> Result<()> {
    assert_eq!(
        qwe(),
        Calculation {
            a: Some(1),
            b: None,
            c: None,
            d: None,
        }
    );
    assert_eq!(
        asd(),
        Calculation {
            a: Some(6),
            b: None,
            c: None,
            d: Some(7),
        }
    );
    assert_eq!(
        zxc(),
        Calculation {
            a: None,
            b: Some(2),
            c: Some(3),
            d: None,
        }
    );

    Ok(())
}
```

Using derive_more crate, we can simplify the code and make it more concise:

```rs
#[derive(Debug, Eq, PartialEq, Default, derive_builder::Builder)]
// setters calls can be chained, each call clones builder
#[builder(pattern = "immutable")]
// if field not set then it would be default (None in our case)
#[builder(default)]
// setter method accepts T as argument and field value would be Some(T)
#[builder(setter(strip_option))]
struct Calculation {
    a: Option<i32>,
    b: Option<i32>,
    c: Option<i32>,
    d: Option<i32>,
    // ... can be more optional fields
}

fn qwe() -> Calculation { /* same as before */ }

fn asd() -> Calculation { /* same as before */ }

fn zxc() -> Calculation { /* same as before */ }
```

The crate generated a builder structure named `CalculationBuilder` with setters for each field.

Now the test can be rewritten much shorter:
```rs
#[test]
fn derive_builder() -> Result<()> {
    let builder = CalculationBuilder::default();
    assert_eq!(qwe(), builder.a(1).build()?);
    assert_eq!(asd(), builder.a(6).d(7).build()?);
    assert_eq!(zxc(), builder.b(2).c(3).build()?);

    Ok(())
}
```

As you can see, now we can assign values only to the required fields, and the test became much shorter. If there were more optional fields in the structure, the gain in brevity and readability would be even higher.

This is just one example of using the `builder` pattern, which is facilitated by this crate. The crate also supports field validation in the `build` method and several types of builders (owned, mutable, immutable).

Perhaps the only downside of this crate, in my opinion, is that the generated `build` method always returns `Result<T>`, even when `T` consists only of optional fields, as in our case.

## insta

Library for snapshot testing. Snapshot represents the expected result of a test, usually stored in a separate file. The library provides a command-line utility for easy snapshot updates. The crate offers many features that can be found in the official [guide](https://insta.rs/docs/).

One of the useful features, in my opinion, is `redactions`. It allows testing values with random or non-deterministic fields order, such as `HashSet`:

```rs
#[derive(serde::Serialize)]
pub struct User {
    id: Uuid,
    username: String,
    flags: HashSet<&'static str>,
}

#[test]
fn redactions() {
    let user = User {
        id: Uuid::new_v4(),
        username: "john_doe".to_string(),
        flags: maplit::hashset! {"zzz", "foo", "aha"},
    };
    insta::assert_yaml_snapshot!(user, {
        ".id" => "[uuid]",
        // make hashset order deterministing
        ".flags" => insta::sorted_redaction()
    });
}
```

For this test, a snapshot `snapshots/insta__tests__redactions.snap` was automatically generated with the following contents:

```rs
---
source: src/bin/insta.rs
expression: user
---
id: "[uuid]"
username: john_doe
flags:
  - aha
  - foo
  - zzz
```

## enum_dispatch

Rust supports polymorphism through static and dynamic dispatch of traits. If you have used dynamic dispatch, you know that it can negatively impact the performance of a program, as the trait implementation is looked up through a vtable at runtime.

This trait allows you to turn dynamic dispatch into static dispatch using an enum. Suppose we have such a trait and its implementations: 

```rs
pub trait ReturnsValue {
    fn return_value(&self) -> usize;
}

pub struct Zero;

impl ReturnsValue for Zero {
    fn return_value(&self) -> usize {
        0
    }
}

pub struct Any(usize);

impl ReturnsValue for Any {
    fn return_value(&self) -> usize {
        self.0
    }
}
```

In this example, we are using dynamic dispatch:
```rs
#[test]
fn derive_dispatch_dynamic() {
    let values: Vec<Box<dyn ReturnsValue>> = vec![Box::new(Zero {}), Box::new(Any(5))];

    assert_eq!(
        values
            .into_iter()
            .map(|dispatched| dispatched.return_value())
            .collect::<Vec<_>>(),
        vec![0, 5]
    );
}
```

Now let's use this trait:
```rs
#[enum_dispatch::enum_dispatch]
pub trait ReturnsValue {
    fn return_value(&self) -> usize;
}

// trait implementations are same

#[enum_dispatch::enum_dispatch(ReturnsValue)]
pub enum EnumDispatched {
    Zero,
    Any,
}

#[test]
fn derive_dispatch_static() {
    let values = vec![EnumDispatched::Zero(Zero {}), EnumDispatched::Any(Any(5))];

    assert_eq!(
        values
            .into_iter()
            .map(|dispatched| dispatched.return_value())
            .collect::<Vec<_>>(),
        vec![0, 5]
    );
}
```

Thus, the crate generated the implementation of the `ReturnsValue` trait for the `EnumDispatched` enum. The creators of the crate conducted performance tests and found that such an implementation can speed up trait usage up to 10-12 times.

In my opinion, the main disadvantage of this library is that you can only [generate an implementation for a trait declared in your crate](https://www.reddit.com/r/rust/comments/a7n5hb/comment/ec5a9ew). Since it is necessary to apply the `#[enum_dispatch::enum_dispatch]` macro directly to the trait (so that `enum_dispatch` can read the function signatures of the trait). Accordingly, it is possible to apply the macro to a trait only in your crate, which you can edit.

## paste
<!--
It lets you concatenate idents (a token that represents an identifiable type, like Path or T) at compile time without nightly, which lets you write macros that take arbitrary $idents and concat them to create types with whatever name you want. From the README, this would define an impl block for a type $name and creates getters for multiple $fields (e.g. a, b, c become get_a, get_b and get_c).

paste! {impl $name {$(pub fn [<get_ $field>](&self) -> &str {&self.$field})*}}
-->

The crate allows concatenating identifiers at compile-time without using nightly. This is useful when writing macros to create arbitrary identifiers using macro variables and static literal identifiers.

Here's a shortened example from the crate's readme. This macro will create an `impl` block for a type with the name `$name` and create getter methods for each `$field`.
```rs
macro_rules! make_a_struct_and_getters {
    ($name:ident { $($field:ident),* }) => {
        // ...

        // Build an impl block with getters. This expands to:
        //     impl S {
        //         pub fn get_a(&self) -> &str { &self.a }
        //         pub fn get_b(&self) -> &str { &self.b }
        //         pub fn get_c(&self) -> &str { &self.c }
        //     }
        paste! {
            impl $name {
                $(
                    pub fn [<get_ $field>](&self) -> &str {
                        &self.$field
                    }
                )*
            }
        }
    }
}

make_a_struct_and_getters!(S { a, b, c });

fn call_some_getters(s: &S) -> bool {
    s.get_a() == s.get_b() && s.get_c().is_empty()
}
```

## either

The general-purpose `Either` enum has two variants `Left` and `Right`. It has a variety of methods and traits for convenient work using this enum.

```rs
use either::Either;

#[test]
fn test() {
    let values = vec![
        Either::Left(1),
        Either::Right(true),
        Either::Left(10),
        Either::Right(false),
    ];
    assert_eq!(
        values
            .into_iter()
            .map(|int_or_bool| -> Either<i32, bool> {
                let int = either::try_left!(int_or_bool);
                Either::Left(int * 2)
            })
            .map(|int_or_bool| { either::for_both!(int_or_bool, s => s.to_string()) })
            .collect::<Vec<_>>(),
        ["2", "true", "20", "false"]
    );
}
```

## num

The collection of numeric traits and types. Includes generics for numbers, big integers, complex numbers, and so on.

```rs
use anyhow::{anyhow, Result};
use num::*;
use std::fmt::Display;

fn bounds_to_string<N: Bounded + Display>(number: N) -> String {
    format!(
        "value {} min is {} max is {}",
        number,
        N::min_value(),
        N::max_value()
    )
}

#[test]
fn bounds() {
    assert_eq!(bounds_to_string(12u8), "value 12 min is 0 max is 255");
    assert_eq!(
        bounds_to_string(33i16),
        "value 33 min is -32768 max is 32767"
    );
}

fn num_operations<N: Num>(a: &str, b: N) -> Result<N> {
    let a = N::from_str_radix(a, 10).map_err(|_| anyhow!("could not conert value"))?;
    let value = a + b - N::one();
    Ok(if value.is_zero() {
        value
    } else {
        value * (N::one() + N::one())
    })
}

#[test]
fn test_num_operations() -> Result<()> {
    assert_eq!(num_operations("2", 10i32)?, 22i32);
    assert_eq!(num_operations("-5", 6i8)?, 0i8);
    Ok(())
}

#[test]
fn greatest_common_divisor() -> Result<()> {
    assert_eq!(num::integer::gcd(25u8, 15u8), 5);
    assert_eq!(num::integer::gcd(1024i32, 65536i32), 1024);
    Ok(())
}
```

## thiserror

The crate provides a macro for implementing the `std::error::Error` trait on structs and enums.

From the error handling perspective, there are two types of crates: libraries and applications. A library is created as a third-party dependency that will be used in applications. For library crates, it is important that the calling code can check, if necessary, what type of error occurred in the library code, and implement different behaviors for different types of errors. For example, ignore I/O errors, but panic on data format errors. For applications, the specific type of errors is usually not important, so application functions usually return a `Result<T, anyhow::Error>` type, as `anyhow` allows convenient conversion of any error into the `anyhow::Error` type using the `?` operator or `From` trait. More details can be found here: [[1]](https://blog.burntsushi.net/rust-error-handling/) (a slightly old article) and [[2]](https://www.shuttle.rs/blog/2022/06/30/error-handling) (a newer one).

This crate is mainly used for convenient error implementation in library crates.

Usage example:
```rs
#[derive(thiserror::Error, Debug)]
pub enum SomeError {
    #[error("io error")]
    Io(#[from] std::io::Error),
    #[error("int parsing error")]
    ParseInt(#[from] std::num::ParseIntError),
    #[error("unknown error")]
    General(#[from] anyhow::Error),
}

/// library func
fn int_error(s: &str) -> Result<i32, SomeError> {
    let num = i32::from_str_radix(s, 10)?;
    Ok(num + 2)
}

#[test]
fn test() {
    // application code
    assert!(matches!(int_error("abc").unwrap_err(), SomeError::ParseInt(_)));
    assert!(matches!(
        std::io::Error::new(std::io::ErrorKind::Other, "oh no!").into(),
        SomeError::Io(_)
    ));
}
```

In the example above, the `std::num::ParseIntError` error was converted to the `SomeError::ParseInt` enum. Without this crate, we would have had to manually write all these conversions.

## rayon

This crate makes it easier to use parallelism in Rust. It is suitable for converting sequential iterators into parallel ones. It guarantees the absence of data races. Parallel iterators adapt their behavior at runtime for maximum performance.

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

In the example above, a sequential iterator was turned into a parallel one by simply changing `iter()` to `par_iter()`.

## crossbeam
<!--
The scope and the AtomicCell are especially useful when implementing safe abstractions of low level data structures

channel implementation is considerably more efficient than the std one
-->

The crate provides a set of tools for concurrent programming: atomics, data structures, memory management, thread synchronization, and more.

For example, the implementation of channels in this crate is more performant compared to std channels (according to the developers), and allows multiple producers and multiple consumers (multi-producer multi-consumer), unlike std channels which only allow a single consumer (multi-producer single-consumer).

## async_trait

The crate allows defining traits with async functions. Currently, Rust does not support async traits at the language syntax level, so you can use the macro provided by this crate with the same name as the trait. You can read more about why async fn in traits are hard in this [article](https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/).

```rs
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;
    }
}
```

The macro changes the function signatures to return `Pin<Box<dyn Future + Send + 'async_trait>>`.

## fs-err

This crate contains wrapper functions with human-readable errors for functions from `std::fs`.

If you have used functions from `std::fs` (such as `read_to_string` or `write`), you may have noticed that in case of an error, the error message is not very informative:
```rs
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)
```

With the `fs-err` crate, we can get more detailed error messages, such as which file does not exist:

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

## tempfile

This crate provides an API for creating temporary files and directories.

```rs
// 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);
```

## bincode

This crate provides encoding and decoding of structures to and from byte arrays. It uses a compact data format that is suitable for storage on disk and for exchanging data between systems with different processor architectures.

```rs
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(())
}
```

## maplit

The crate provides macros for generating container types from `std`. It is largely a matter of personal preference, as containers already have `from` and `from_iter` methods. There is an open [RFC](https://github.com/rust-lang/rfcs/issues/542) on this topic.

```rs
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]),
]);
```

## indexmap
<!--
when insertion ordered maps are needed
The distinction here is not just that the map is ordered, but that it (mostly) preserves insertion order
-->

An ordered hash map that preserves the insertion order of elements. This means that iterating over the elements of the hash map will occur in the same order as the insertion order of the elements. This order is preserved until you call the `remove` method. The hash map supports searching for elements by key and by numeric index (like an array) and fast iteration over elements. All these properties arise from the fact that it [stores](https://github.com/bluss/indexmap/blob/11ac52c3c828a42d69c5fb3248198511836bfd2f/src/map/core.rs#L24-L30) a vector of key-value pairs and a hash table mapping keys' hashes to their indices in the vector. It's worth using if these properties fit your use case.

## getset

This crate will be appreciated by former Java programmers. The crate contains procedural macros for generating getter and setter methods.

```rs
use getset::{CopyGetters, Getters, MutGetters, Setters};

#[derive(Getters, Setters, MutGetters, CopyGetters, Default)]
pub struct Foo<T>
where
    T: Copy + Clone + Default,
{
    /// Doc comments are supported!
    /// Multiline, even.
    #[getset(get, set, get_mut)]
    private: T,

    /// Doc comments are supported!
    /// Multiline, even.
    #[getset(get_copy = "pub", set = "pub", get_mut = "pub")]
    public: T,
}

fn main() {
    let mut foo = Foo::default();
    foo.set_private(1);
    (*foo.private_mut()) += 1;
    assert_eq!(*foo.private(), 2);
}
```

## mockall

This crate provides automatic mock object generation for (almost all) traits and structures. These objects can be used in unit tests instead of objects of the original type, which can make it easier to write high-level unit tests or test complex edge cases.

```rs
#[cfg(test)]
use mockall::{automock, predicate::*};

#[cfg_attr(test, automock)]
trait CalcTrait {
    fn foo(&self, x: u32) -> u32;
}

fn calculation(calc: impl CalcTrait, x: u32) -> u32 {
    calc.foo(x)
}

#[test]
fn test() {
    let mut mock = MockCalcTrait::new();
    mock.expect_foo().with(eq(4)).times(1).returning(|x| x + 1);

    assert_eq!(5, calculation(mock, 4));
}
```

Mock objects can be automatically generated using the `#[automock]` attribute macro. However, it has its limitations, so sometimes you have to use the procedural macro `mock!` with a more manual implementation of mock objects.

## quickcheck

QuickCheck is a framework for property-based testing. It allows testing code with a large number of arbitrary input data. If an error is found, it automatically finds the minimal test case to reproduce the error.

```rs
#[cfg(test)]
mod tests {
    fn reverse<T: Clone>(xs: &[T]) -> Vec<T> {
        let mut rev = vec!();
        for x in xs {
            rev.insert(0, x.clone())
        }
        rev
    }

    #[quickcheck]
    fn double_reversal_is_identity(xs: Vec<isize>) -> bool {
        xs == reverse(&reverse(&xs))
    }
}
```

## proptest

Like `quickcheck`, `proptest` is a property-based testing framework. However, it has a [more flexible input data generation](https://github.com/proptest-rs/proptest/blob/master/proptest/README.md#differences-between-quickcheck-and-proptest) in contrast to `quickcheck`, although for complex data it may take significantly longer to run than `quickcheck`.

```rs
proptest! {
    #[test]
    fn doesnt_crash(s in "\\PC*") {
        parse_date(&s);
    }

    #[test]
    fn parses_date_back_to_original(y in 0u32..10000,
                                    m in 1u32..13,
                                    d in 1u32..32)
    {
        let result = parse_date(&format!("{:04}-{:02}-{:02}", y, m, d)).unwrap();

        prop_assert_eq!((y, m, d), result);
    }
}
```

## heck

A library for converting text into various commonly used variable naming styles, such as `CamelCase`, `snake_case`, and others.

For example, when you use the [rename_all](https://docs.rs/sqlx/latest/sqlx/trait.FromRow.html#rename_all) attribute in the `sqlx` library, it [uses](https://github.com/launchbadge/sqlx/blob/4f1ac1d6060ee73edf83c8365fafb12df44deecc/sqlx-macros-core/src/derives/mod.rs#L13) the functionality of `heck`.

```rs
use heck::ToShoutyKebabCase;

#[test]
fn test() {
    assert_eq!("i am very angry!".to_shouty_kebab_case(), "I-AM-VERY-ANGRY");
}
```

## num_cpus

A small crate that helps determine the number of physical CPU cores or the number of parallel tasks that can be efficiently executed on the system.

For example, I used it to [determine the number of threads](https://github.com/artslob/ray-tracing-one-weekend/blob/f39a09a18a9c52543c8bf7ad928f8d32e530ba24/src/main.rs#L67) when going through the tutorial [Ray Tracing in One Weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html).

## humantime

This library provides a formatter and parser for `std::time::{Duration, SystemTime}` in a human-readable format. It also has integration with `serde` through the `humantime-serde` crate. This allows, for example, specifying `Duration` values in the application/service config in a readable format instead of using unit of measurement in the variable name, reducing the likelihood of errors:
```yaml
# for example instead of this:
timeout_mins: 120
# you can write this:
timeout: 2 hours
```

Usage example:
```rs
use serde::{Deserialize, Serialize};
use std::time::Duration;

#[test]
fn format() {
    let duration = Duration::new(9420, 0);
    let as_str = "2h 37m";
    assert_eq!(humantime::format_duration(duration).to_string(), as_str);
    assert_eq!(humantime::parse_duration(as_str), Ok(duration));
}

#[derive(Serialize, Deserialize)]
struct Foo {
    #[serde(with = "humantime_serde")]
    timeout: Duration,
}

#[test]
fn serde() {
    let input = r#" { "timeout": "3 days 1hour 12min 5s" } "#;
    let foo: Foo = serde_json::from_str(input).unwrap();
    assert_eq!(foo.timeout, Duration::new(263525, 0));
}
```

## overload

This crate provides a macro for easier implementation of trait operators. This crate is useful when a more complex implementation of an operator is needed. In the example below, we generated addition of two different types, which actually works as `a * b + 1`. For simpler cases, the `derive_more` crate will be more suitable.

```rs
use overload::overload;
use std::ops;

#[derive(PartialEq, Debug)]
struct A {
    v: i32,
}

#[derive(PartialEq, Debug)]
struct B {
    v: i32,
}

// ? below generate operator for A and &A values
overload!((a: ?A) + (b: ?B) -> B { B { v: a.v * b.v + 1 } });

#[test]
fn test() {
    assert_eq!(&A { v: 3 } + B { v: 5 }, B { v: 16 });
}
```

## enum-iterator

Macros for generating iterators over the values of an enum or structure.

```rs
use enum_iterator::{all, first, last, next, Sequence};
use itertools::Itertools;

#[derive(Debug, PartialEq, Sequence)]
enum Direction {
    Left,
    Middle,
    Right,
}

#[test]
fn test_enum() {
    use Direction::*;

    assert_eq!(all::<Direction>().collect_vec(), vec![Left, Middle, Right]);
    assert_eq!(first::<Direction>(), Some(Left));
    assert_eq!(last::<Direction>(), Some(Right));
    assert_eq!(next(&Middle), Some(Right));
}

#[derive(Debug, PartialEq, Sequence)]
struct Foo {
    a: bool,
    b: u8,
}

#[test]
fn test_struct() {
    let expected_number_of_elements = 512;
    assert_eq!(
        enum_iterator::cardinality::<Foo>(),
        expected_number_of_elements
    );
    assert_eq!(first::<Foo>(), Some(Foo { a: false, b: 0 }));
    assert_eq!(last::<Foo>(), Some(Foo { a: true, b: 255 }));
}
```

## cfg-if

This crate provides convenient declaration of items that depend on a large number of `#[cfg]` configurations in the form of if-else expressions.

```rs
cfg_if::cfg_if! {
    if #[cfg(unix)] {
        fn foo() { /* unix specific functionality */ }
    } else if #[cfg(target_pointer_width = "32")] {
        fn foo() { /* non-unix, 32-bit functionality */ }
    } else {
        fn foo() { /* fallback implementation */ }
    }
}
```

## arrayref

The macros for conveniently creating arrays from slices.

```rs
let addr: &[u8; 16] = ...;
let mut segments = [0u16; 8];
// array-based API
for i in 0 .. 8 {
    let mut two_bytes = [addr[2*i], addr[2*i+1]];
    segments[i] = read_u16_array(&two_bytes);
}
// array-based API with arrayref
for i in 0 .. 8 {
    segments[i] = read_u16_array(array_ref![addr, 2*i, 2]);
}
```

## educe

This crate provides procedural macros for faster, flexible and declarative implementation of traits from the standard library, like `Debug`, `Eq`, `Ord`, `Deref` and so on. The flexibility lies in the ability to exclude fields from implementation, include trait bounds, and so on.

```rs
#[derive(educe::Educe)]
// note `new` below: generate `new()` that calls Default
#[educe(Default(new))]
#[derive(Debug, PartialEq)]
struct Struct {
    #[educe(Default = 3)]
    f1: u8,
    #[educe(Default = true)]
    f2: bool,
    #[educe(Default = "Hello")]
    f3: String,
}

#[test]
fn test() {
    let expected = Struct {
        f1: 3,
        f2: true,
        f3: String::from("Hello"),
    };
    assert_eq!(Struct::default(), expected);
    assert_eq!(Struct::new(), expected);
}
```

## derivative

This crate also provides macros for implementing traits from the standard library, similar to `educe`. However, the last update of this library was in January 2021.

```rs
#[derive(Derivative)]
#[derivative(PartialEq)]
struct Foo {
    foo: u8,
    #[derivative(PartialEq="ignore")]
    bar: u8,
}

assert!(Foo { foo: 0, bar: 42 } == Foo { foo: 0, bar: 7});
assert!(Foo { foo: 42, bar: 0 } != Foo { foo: 7, bar: 0});
```

## chronoutil

In Rust, the `Duration` type is used to manipulate dates, which represents a fixed number of seconds and nanoseconds. The `chrono::Duration` has constructor functions named `weeks`, `days`, `hours`, but it doesn't have a `month` constructor because it is a relative value that cannot be expressed in seconds. Therefore, if you want to manipulate dates in more human-readable units, such as adding a month or a year, you can use the tools provided by this crate.

```rs
let delta = RelativeDuration::months(1) + RelativeDuration::days(1);
assert_eq!(
    NaiveDate::from_ymd(2021, 1, 28) + delta,
    NaiveDate::from_ymd(2021, 3, 1)
);
assert_eq!(
    NaiveDate::from_ymd(2020, 1, 28) + delta,
    NaiveDate::from_ymd(2020, 2, 29)
);
```

## References
1. https://www.reddit.com/r/rust/comments/uevmnx/what_crates_would_you_consider_essential/
3. https://www.reddit.com/r/rust/comments/ylp4nz/what_crates_are_considered_as_defacto_standard/
4. https://blessed.rs/crates
5. https://lib.rs/
6. https://crates.io/crates?sort=recent-downloads
7. https://www.reddit.com/r/rust/comments/nuq1ix/whats_your_favourite_underrated_rust_crate_and_why/