Book Image

Creative Projects for Rust Programmers

By : Carlo Milanesi
Book Image

Creative Projects for Rust Programmers

By: Carlo Milanesi

Overview of this book

Rust is a community-built language that solves pain points present in many other languages, thus improving performance and safety. In this book, you will explore the latest features of Rust by building robust applications across different domains and platforms. The book gets you up and running with high-quality open source libraries and frameworks available in the Rust ecosystem that can help you to develop efficient applications with Rust. You'll learn how to build projects in domains such as data access, RESTful web services, web applications, 2D games for web and desktop, interpreters and compilers, emulators, and Linux Kernel modules. For each of these application types, you'll use frameworks such as Actix, Tera, Yew, Quicksilver, ggez, and nom. This book will not only help you to build on your knowledge of Rust but also help you to choose an appropriate framework for building your project. By the end of this Rust book, you will have learned how to build fast and safe applications with Rust and have the real-world experience you need to advance in your career.
Table of Contents (14 chapters)

Understanding the different editions of Rust

On December 6, 2018, a very important version of the Rust language, its compiler, and its standard library was released: stable version 1.31. This version has been defined as the 2018 edition, meaning it is a milestone that will be used as a reference for the years to come.

Before this, there was another version, 1.0, which was defined as the 2015 edition. This edition was characterized by the word stability. Up until version 1.0, every version of the compiler applied breaking changes to the language or to the standard library, forcing the developers to apply sweeping changes to their code base. From version 1.0, efforts have been made to ensure that any future version of the compiler can correctly compile any code written for version 1.0 or successive versions. This is called backward compatibility.

However, many features were applied to the language and to the standard library before the release of the 2018 edition. Many new libraries used these new features, meaning that these libraries could not be used by older compilers. For this reason, there was a need to tag a specific version of Rust as aimed at being used with newer libraries. This was the main reason for the 2018 edition.

Some of the features added to the language are marked as for the 2015 edition, while others are marked as for the 2018 edition. The features for the 2015 edition are just small improvements, while the features for the 2018 edition are more in-depth changes. Developers must mark their crates as for the 2018 edition in order to use the features that are specific to the 2018 edition.

In addition, although the 2015 edition marked a stable milestone for the language and the standard library, the command-line tools were not actually stabilized; they were still quite immature. In the three and a half years from May 2015 to December 2018, the main official command-line tools have matured, and the language has also been improved to allow more efficient coding. The 2018 edition can be characterized by the word productivity.

The following table shows a timeline of the features stabilized in the language, the standard library, and the tooling:

2015 May: 2015 edition August: Parallel compilation on multi-core CPUs
2016 April: Microsoft C compiler format supported May: Ability to capture panics September: Improved compiler error messages November: The ? operator December: The rustup command
2017 February: Custom derive attributes March: The cargo check command July: The union keyword August: Associated constants November: The ? operator with Option
2018 February:
  • The formation of four Domain Working Groups.
  • The rustfmt program
May:
  • The Rust Programming Language Second Edition.
  • The impl Trait language feature.
  • main can return a Result.
  • Inclusive ranges with ..=
  • The i128 and u128 native types.
  • Improved patterns for match
June:
  • The SIMD library feature
  • The dyn Trait language feature
August: Custom global allocator September:
  • The cargo fix command
  • The cargo clippy command
October:
  • Procedural macros
  • Changes to the module system and the use statement
  • Raw identifiers
  • no_std applications
December:
  • The 2018 edition
  • Non-lexical lifetimes
  • The const fn language feature
  • The new https://www.rust-lang.org/ website
  • try, async, and await are reserved words

Many improvements have been applied since the 2015 edition. More information can be found in the official documentation (https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html). The most important improvements are listed as follows:

  • A new official tutorial book, available free online (https://doc.rust-lang.org/book/), or printed on paper (The Rust Programming Language by Steve Klabnik and Carol Nichols).
  • A revamped official website.
  • The formation of four domain working groups, which are open committees to design the future of the ecosystem in four key areas:
    • Networking: Designing the new asynchronous paradigm around a concept of delayed computation, named future, as it is already done in other languages, such as C++, C#, and JavaScript (with promises).
    • Command-line applications: Designing some standard libraries to support any non-graphical, non-embedded applications.
    • WebAssembly: Designing tools and libraries to build applications to be run inside web browsers.
    • Embedded software: Designing tools and libraries to build applications to be run on bare-metal systems or on strictly constrained hardware.
  • We witnessed some good improvements to the language:
    • Non-lexical lifetimes; any bindings that are no longer used are considered dead. For example, now this program is allowed:
fn main() {
let mut _a = 7;
let _ref_to_a = &_a;
_a = 9;
}
In this code, the object bound to the variable _a is borrowed by the variable _ref_to_a in the second statement. Prior to the introduction of non-lexical lifetimes, such bindings would last till the end of the scope, and so the last statement would have been illegal because it tries to change that object through binding _a when it is still borrowed to variable _ref_to_a. Now, because variable _ref_to_a is no longer used, its lifetime ceases in the same line it is declared, and so, in the last statement, variable _a is again free to change its own object.
    • The Impl Trait feature, which allows functions to return unspecified types, such as closures.
    • The i128 and u128 native types.
    • Some other reserved keywords such as try, async, and await.
    • The ? operator, usable even in the main function, because now it can return Result. The following program is an example of the main function returning a Result:
fn main() -> Result<(), String> {
Err("Hi".to_string())
}

It can succeed, by returning the usual empty tuple or fail by returning the type you specify. In this case, it was String. The following program is an example using the ? operator used in the main function:

fn main() -> Result<(), usize> {
let array = [12, 19, 27];
let found = array.binary_search(&19)?;
println!("Found {}", found);
let found = array.binary_search(&20)?;
println!("Found {}", found);
Ok(())
}

This program will print Found 1 on the standard output stream, meaning that the number 19 has been found at position 1, and it will print Error: 2 on the standard error stream, meaning that the number 20 hasn't been found, but that it should be inserted at position 2.

    • Procedural macros, which allow a kind of meta-programming, manipulating source code to generate Rust code at compile time.
    • More powerful and more ergonomic pattern matching in match expressions.
  • And also some improvements to the standard tooling:
    • The rustup program, which allows users to easily choose the default compiler target or to update the toolchain.
    • The rustfix program, which converts a 2015 edition project to a 2018 edition project.
    • The Clippy program, which checks for non-idiomatic syntax, and suggests changes to code for better maintainability.
    • Faster compilation speed, in particular, if just a syntax check is required.
    • The Rust Language Server (RLS) program, which is currently still unstable, but which allows IDEs and programmable editors to spot syntax errors, and to suggest allowed operations.

Rust is still evolving as a language, like any other programming language. The following areas are still left to be improved:

  • The IDE tools, including a language interpreter (REPL) and a graphical debugger
  • Libraries and tools to support bare-metal and real-time software development
  • Application-level frameworks and libraries for the main application areas

This book will focus primarily on the third point on this list.