Importing Crates

Now that you know how to organize your Rust project. Let's look at how 3rd party Crates can be added to the application. Dependencies are, amongst other things, managed By the Cargo.toml file.

This is the Cargo.toml file that was generated for our HelloWorld example:

[package]
name = "hello_rust_world"
version = "0.1.0"
authors = ["Marcel <[email protected]>"]
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

To add a dependency, often you just need to add a single line to the [dependencies] section. To import the rand crate version 0.7.3, you would add this line:

[dependencies]
rand = "0.7.3"

You can find the latest version of a crate on crates.io.

Instead of editing cargo.toml manually, you can use the cargo add command line tool to add a dependency. For example, to add the serde-json crate, you would run:

$ cargo add serde-json                                                                                                                                                                        13:02:26  ☁  main ☂ ⚡ ✭
    Updating crates.io index
warning: translating `serde-json` to `serde_json`
      Adding serde_json v1.0.114 to dependencies.
             Features:
             + std
             - alloc
             - arbitrary_precision
             - float_roundtrip
             - indexmap
             - preserve_order
             - raw_value
             - unbounded_depth
    Updating crates.io index

As you can see, the cargo add command automatically translates the crate name to the correct name, and adds the latest version of the crate to the Cargo.toml file. It also lists the features that are available for the crate.

Limiting the features

When you add a dependency, Cargo will automatically import all the default features of that crate. This is usually what you want, as it makes the crate easier to use. When more control is required, additional parameters can be passed. You can, for example, extend and limit the features you are importing, by passing the features argument:

[dependencies]
serde = { version = "1.0.106", features = ["derive"] }

This will import the serde crate version 1.0.106, including the derive feature.

In case you do not want to import the default features, you can pass the default-features = false argument:

chrono = { version = "0.4", default-features = false, features = [
    "clock",
    "std",
] }

In this example, the chrono crate version 0.4 is imported, but without the default features. Instead, the clock and std features are imported.

Importing from Git or local

Sometimes you need a Crate that is not publicly published, in that case you can import directly from a Git repository:

[dependencies]
kp-lib-rs = { git = "https://bitbucket.forge.somewhere.com/scm/someservice/rust_common.git", tag = "v0.0.555", features = ["common", "smgr"] }

You can also import a Crate from your local machine:

[dependencies]
smgr_model = { path = "../smgr_model" }

Random numbers

Let's try this out extend our HelloWorld example, to generate a bunch of random numbers.

In RustRover when you are adding a dependency, you can press Ctrl + Space while the cursor is between the "" to get the latest version of that dependency.

Once you have added the dependency to the Cargo.toml, a symbol with three stacked crates appear in front of the dependency. When you click on that icon, you are automatically taken to the documentation of that crate, for that particular version.

Filename: Cargo.toml

[package]
name = "random_numbers"
version = "0.1.0"
authors = ["Marcel <[email protected]>"]
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.7.3"

Filename: main.rs

use rand::prelude::*;

fn main() {
    let mut rng = rand::thread_rng();

    for _i in 1..10 {
        let random_number: u8 = rng.gen(); // generates an integer between 0 and 255
        println!("Generated: {}", random_number);
    }
}

Reference material