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
- Data Serialization / Deserialization with Serde
- Command Line User Interface with Clap
- Rust CLI Apps withÂ
rust-starter
- Colorful Terminals withÂ
termion
- Final Thoughts
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 Rails, Flask, 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.
For a better experience with command line apps, I would use the crate StructOpt, which is an ergonomic data-driven layer over Clap. Much nicer to use. Secondly, I think Termion has a horrible interface. I much prefer the crate “Colored” for coloured output.