Book Image

Rust Quick Start Guide

By : Daniel Arbuckle
Book Image

Rust Quick Start Guide

By: Daniel Arbuckle

Overview of this book

Rust is an emerging programming language applicable to areas such as embedded programming, network programming, system programming, and web development. This book will take you from the basics of Rust to a point where your code compiles and does what you intend it to do! This book starts with an introduction to Rust and how to get set for programming, including the rustup and cargo tools for managing a Rust installation and development work?ow. Then you'll learn about the fundamentals of structuring a Rust program, such as functions, mutability, data structures, implementing behavior for types, and many more. You will also learn about concepts that Rust handles differently from most other languages. After understanding the Basics of Rust programming, you will learn about the core ideas, such as variable ownership, scope, lifetime, and borrowing. After these key ideas, you will explore making decisions in Rust based on data types by learning about match and if let expressions. After that, you'll work with different data types in Rust, and learn about memory management and smart pointers.
Table of Contents (10 chapters)

Starting a new project

Okay, so we've installed the compiler. Yay! But how do we use it?

The first step is to open up a command-line window, and navigate to the directory where we want to store our new project. Then we can create the skeleton of a new program with cargo new foo.

When we do this, cargo will create a new directory named foo and set up the skeletal program inside it.

The default is for cargo to create the skeleton of an executable program, but we can also tell it to set up a new library for us. All that takes is an additional command-line argument (bar is the name of the new directory that will be created, like foo): cargo new --lib bar.

When we look inside the newly created foo directory, we see a file called Cargo.toml and a sub-directory called src. There may also be a Git version control repository, which we will ignore for now.

Project metadata

The Cargo.toml file is where metadata about the program is stored. That includes the program's name, version number, and authors, but importantly it also has a section for dependencies. Editing the content of the [dependencies] section is how we tell Rust that our code should be linked to external libraries when it is compiled, which libraries and versions to use, and where to find them. External libraries are collections of source code that were packaged up in order to make them easy to use as components of other programs. By finding and linking good libraries, we can save the time and effort of writing our whole program ourselves. Instead, we can write only the part that nobody else has already done.

By the way, .toml files are written in Tom's Obvious, Minimal Language (TOML), a more well-defined and feature-complete version of the old .ini format that Microsoft popularized but never standardized. TOML is becoming quite popular, and is supported and used in a wide variety of languages and applications. You can find the language specification at https://github.com/toml-lang/toml.

Dependencies on libraries from crates.io

If a library that our program depends on is published on https://crates.io/, all we have to do to link it is add its linking code to the dependencies section. Let's say we want to use serde (a tool for turning Rust data into formats such as JSON and back) in our program. First, we find its linking code with: cargo search serde.

I originally found out about serde by browsing through crates.io, an exploration that I would encourage you to try as well.

This will print out a list of matches that looks something like this:


serde = "1.0.70" # A generic serialization/deserialization framework
serde_json = "1.0.24" # A JSON serialization file format
serde_derive_internals = "0.23.1" # AST representation used by Serde derive macros. Unstable.
serde_any = "0.5.0" # Dynamic serialization and deserialization with the format chosen at runtime
serde_yaml = "0.7.5" # YAML support for Serde
serde_bytes = "0.10.4" # Optimized handling of `&[u8]` and `Vec<u8>` for Serde
serde_traitobject = "0.1.0" # Serializable trait objects. This library enables the serialization of trait objects such…
cargo-ssearch = "0.1.2" # cargo-ssearch: cargo search on steroids
serde_codegen_internals = "0.14.2" # AST representation used by Serde codegen. Unstable.
serde_millis = "0.1.1" # A serde wrapper that stores integer millisecond value for timestamps and duration…
... and 458 crates more (use --limit N to see more)

The first one is the core serde library, and the linking code is the part of the line before the # symbol. All we have to do is copy and paste that into the dependencies section of Cargo.toml, and Rust will know that it should compile and link serde when it compiles our foo program. So, the dependencies section of Cargo.toml would look like this:

 [dependencies]
serde = "1.0.70"

Dependencies on Git repositories

Depending on a library stored in the Git version control system, either locally or remotely, is also easy. The linking code is slightly different, but it looks like this:

    [dependencies]
thing = { git = "https://github.com/example/thing" }

We tell Rust where to find the repository, and it knows how to check it out, compile it, and link it with our program. The repository location doesn't have to be a URL; it can be any repository location that the git command recognizes.

Dependencies on local libraries

We can also link against other libraries stored on our own systems, of course. To do this, we just have to add an entry such as this to our Cargo.toml file:


[dependencies]
example = { path = "/path/to/example" }

The path can be absolute or relative. If it's relative, it's interpreted as being relative to the directory containing our Cargo.toml file.

Automatically generated source files

When creating an executable program, cargo adds a file called main.rs to our project as it is created. For a newly created library, it instead adds lib.rs. In either case, that file is the entry point for the whole project.

Let's take a look at the boilerplate main.rs file:

     fn main() {
println!("Hello, world!");
}

Simple enough, right? Cargo's default program is a Rust version of the classic hello world program, which has been re-implemented countless times by new programmers in every conceivable programming language.

If we look at a new library's lib.rs file, things are a little more interesting:

     #[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

Instead of having a main function, which all executable programs need because they need a place to start, the library boilerplate includes a framework for automated tests and a single test that confirms that 2 + 2 = 4.