5 Useful Rust crates you should use in your next project

light inside library Photo by Janko Ferlic on Pexels.com

Are you planning your next Rust project? You should check out these crates.

The Rust ecosystem has been steadily growing over the last few years. You have a use case to solve, and not sure what crate does the best job for that? Let’s get into it.

Table of Contents

Build web applications with Rocket / Web Framework

Rocket is an async web framework for Rust focusing on usability, security, extensibility, and speed.

If you plan to build a web application with Rust, Rocket is the tool of choice.

Here’s the Hello World:

#[macro_use] extern crate rocket;

#[get("/<name>/<age>")]
fn hello(name: &str, age: u8) -> String {
    format!("Hello, {} year old named {}!", age, name)
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/hello", routes![hello])
}

Source: GitHub

It bears many similarities to frameworks like RailsFlask, or Bottle.

Data Serialization / Deserialization with Serde

Whenever you need to serialize or deserialize data in your application, serde comes in handy. Most common use case: Handling JSON data.

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 1, y: 2 };

    // Convert the Point to a JSON string.
    let serialized = serde_json::to_string(&point).unwrap();

    // Prints serialized = {"x":1,"y":2}
    println!("serialized = {}", serialized);

    // Convert the JSON string back to a Point.
    let deserialized: Point = serde_json::from_str(&serialized).unwrap();

    // Prints deserialized = Point { x: 1, y: 2 }
    println!("deserialized = {:?}", deserialized);
}

Source: GitHub

In most cases, you annotate your struct as Serializable/Deserializable, and you can start using Serde. No need to write any boilerplate code.
Serde provides support for a lot of different data formats, such as:

  • JSON
  • YAML
  • TOML
  • Bincode
  • BSON

Check out this link for more supported Formats.

Command Line User Interface with Clap

clap is used to parse and validate the string of command line arguments provided by a user at runtime.

Building an intuitive command-line interface helps your users to work effortlessly with your application. With clap, you straightforwardly define arguments and subcommands:

// (Full example with detailed comments in examples/01b_quick_example.rs)
//
// This example demonstrates clap's "builder pattern" method of creating arguments
// which the most flexible but also most verbose.
use clap::{Arg, App};

fn main() {
    let matches = App::new("My Super Program")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg(Arg::new("config")
            .short('c')
            .long("config")
            .value_name("FILE")
            .about("Sets a custom config file")
            .takes_value(true))
        .arg(Arg::new("INPUT")
            .about("Sets the input file to use")
            .required(true)
            .index(1))
        .arg(Arg::new("v")
            .short('v')
            .multiple(true)
            .takes_value(true)
            .about("Sets the level of verbosity"))
        .subcommand(App::new("test")
            .about("controls testing features")
            .version("1.3")
            .author("Someone E. <someone_else@other.com>")
            .arg(Arg::new("debug")
                .short('d')
                .about("print debug information verbosely")))
        .get_matches();

    // You can check the value provided by positional arguments, or option arguments
    if let Some(i) = matches.value_of("INPUT") {
        println!("Value for input: {}", i);
    }

    if let Some(c) = matches.value_of("config") {
        println!("Value for config: {}", c);
    }

    // You can see how many times a particular flag or argument occurred
    // Note, only flags can have multiple occurrences
    match matches.occurrences_of("v") {
        0 => println!("Verbose mode is off"),
        1 => println!("Verbose mode is kind of on"),
        2 => println!("Verbose mode is on"),
        3 | _ => println!("Don't be crazy"),
    }

    // You can check for the existence of subcommands, and if found use their
    // matches just as you would the top level app
    if let Some(ref matches) = matches.subcommand_matches("test") {
        // "$ myapp test" was run
        if matches.is_present("debug") {
            // "$ myapp test -d" was run
            println!("Printing debug info...");
        } else {
            println!("Printing normally...");
        }
    }

    // Continued program logic goes here...
}

Source: GitHub

Rust CLI Apps with rust-starter

rust-starter is an exciting new template to get started with a new application quickly. Instead of spending an hour setting up all sorts of things, rust-starter has everything configured out of the box.

See Getting Started to get started quickly with your next CLI project.

Colorful Terminals with termion

Sometimes, the usual black/white (or whatever color scheme you’re using) terminal color scheme is not cutting it. That’s where termion comes in handy. One of the most straightforward use cases: Applying different colors and formatting your terminal output:

extern crate termion;

use termion::{color, style};

use std::io;

fn main() {
    println!("{}Red", color::Fg(color::Red));
    println!("{}Blue", color::Fg(color::Blue));
    println!("{}Blue'n'Bold{}", style::Bold, style::Reset);
    println!("{}Just plain italic", style::Italic);
}

Source: GitLab

Final Thoughts

This is a small selection of all the Rust libraries out there. Developers release new projects daily. To stay up to date with Rust, make sure to follow This Week in Rust.