0% found this document useful (0 votes)
29 views26 pages

Comprehensive Rust Course Overview

Comprehensive Rust is a four-day course designed to teach Rust programming from basic syntax to advanced topics, including Android-specific content on the final day. The course aims to provide a thorough understanding of Rust, enabling participants to write and modify Rust programs, while not covering Android application development. Participants are expected to have prior programming knowledge, and the course structure includes interactive sessions with practical exercises.

Uploaded by

Josiah Rodriguez
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views26 pages

Comprehensive Rust Course Overview

Comprehensive Rust is a four-day course designed to teach Rust programming from basic syntax to advanced topics, including Android-specific content on the final day. The course aims to provide a thorough understanding of Rust, enabling participants to write and modify Rust programs, while not covering Android application development. Participants are expected to have prior programming knowledge, and the course structure includes interactive sessions with practical exercises.

Uploaded by

Josiah Rodriguez
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Welcome to Comprehensive Rust 🦀

This is a four day Rust course developed by the Android team. The course covers the full spectrum
of Rust, from basic syntax to advanced topics like generics and error handling. It also includes
Android-specific content on the last day.

The goal of the course is to teach you Rust. We assume you don’t know anything about Rust and
hope to:

Give you a comprehensive understanding of the Rust syntax and language.


Enable you to modify existing programs and write new programs in Rust.
Show you common Rust idioms.

On Day 4, we will cover Android-specific things such as:

Building Android components in Rust.


AIDL servers and clients.
Interoperability with C, C++, and Java.

It is important to note that this course does not cover Android application development in Rust, and
that the Android-specific parts are specifically about writing code for Android itself, the operating
system.

Non-Goals
Rust is a large language and we won’t be able to cover all of it in a few days. Some non-goals of this
course are:

Learn how to use async Rust — we’ll only mention async Rust when covering traditional
concurrency primitives. Please see Asynchronous Programming in Rust instead for details on
this topic.
Learn how to develop macros, please see Chapter 19.5 in the Rust Book and Rust by Example
instead.

Assumptions
The course assumes that you already know how to program. Rust is a statically typed language and
we will sometimes make comparisons with C and C++ to better explain or contrast the Rust
approach.

If you know how to program in a dynamically typed language such as Python or JavaScript, then you
will be able to follow along just fine too.

Speaker Notes

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Running the Course

This page is for the course instructor.

Here is a bit of background information about how we’ve been running the course internally at
Google.

To run the course, you need to:

1. Make yourself familiar with the course material. We’ve included speaker notes on some of the
pages to help highlight the key points (please help us by contributing more speaker notes!).
You should make sure to open the speaker notes in a popup (click the link with a little arrow
next to “Speaker Notes”). This way you have a clean screen to present to the class.

2. Decide on the dates. Since the course is large, we recommend that you schedule the four days
over two weeks. Course participants have said that they find it helpful to have a gap in the
course since it helps them process all the information we give them.

3. Find a room large enough for your in-person participants. We recommend a class size of 15-20
people. That’s small enough that people are comfortable asking questions — it’s also small
enough that one instructor will have time to answer the questions.

4. On the day of your course, show up to the room a little early to set things up. We recommend
presenting directly using mdbook serve running on your laptop. This ensures optimal
performance with no lag as you change pages. Using your laptop will also allow you to fix typos
as you or the course participants spot them.

5. Let people solve the exercises by themselves or in small groups. Make sure to ask people if
they’re stuck or if there is anything you can help with. When you see that several people have
the same problem, call it out to the class and offer a solution, e.g., by showing people where to
find the relvant information in the standard library.

6. If you don’t skip the Android specific parts on Day 4, you will need an AOSP checkout. Make a
checkout of the course repository on the same machine and move the src/android/ directory
into the root of your AOSP checkout. This will ensure that the Android build system sees the
[Link] files in src/android/ .

Ensure that adb sync works with your emulator or real device and pre-build all Android
examples using src/android/build_all.sh . Read the script to see the commands it runs and
make sure they work when you run them by hand.

That is all, good luck running the course! We hope it will be as much fun for you as it has been for us!

Please provide feedback afterwards so that we can keep improving the course. We would love to
hear what worked well for you and what can be made better. Your students are also very welcome
to send us feedback!

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Course Structure

This page is for the course instructor.

The course is fast paced and covers a lot of ground:

Day 1: Basic Rust, ownership and the borrow checker.


Day 2: Compound data types, pattern matching, the standard library.
Day 3: Traits and generics, error handling, testing, unsafe Rust.
Day 4: Concurrency in Rust and interoperability with other languages

Exercise for Day 4: Do you interface with some C/C++ code in your project which we could
attempt to move to Rust? The fewer dependencies the better. Parsing code would be ideal.

Format
The course is meant to be very interactive and we recommend letting the questions drive the
exploration of Rust!

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Keyboard Shortcuts
There are several useful keyboard shortcuts in mdBook:

Arrow-Left : Navigate to the previous page.


Arrow-Right : Navigate to the next page.
Ctrl + Enter : Execute the code sample that has focus.
s : Activate the search bar.

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Using Cargo
When you start reading about Rust, you will soon meet Cargo, the standard tool used in the Rust
ecosystem to build and run Rust applications. Here we want to give a brief overview of what Cargo is
and how it fits into the wider ecosystem and how it fits into this training.

Installation

Rustup (Recommended)

You can follow the instructions to install cargo and rust compiler, among other standard ecosystem
tools with the rustup tool, which is maintained by the Rust Foundation.

Along with cargo and rustc, Rustup will install itself as a command line utility that you can use to
install/switch toolchains, setup cross compilation, etc.

Package Managers

Debian

On Debian/Ubuntu, you can install Cargo and the Rust source with

$ sudo apt install cargo rust-src

This will allow rust-analyzer to jump to the definitions. We suggest using VS Code to edit the code
(but any LSP compatible editor works).

Some folks also like to use the Jetbrains family of IDEs, which do their own analysis but have their
own tradeoffs. If you prefer them, you can install the Rust Plugin. Please take note that as of January
2023 debugging only works on the CLion version of the Jetbrains IDEA suite.

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
The Rust Ecosystem
The Rust ecosystem consists of a number of tools, of which the main ones are:

rustc : the Rust compiler which turns .rs files into binaries and other intermediate formats1.

cargo : the Rust dependency manager and build tool. Cargo knows how to download
dependencies hosted on [Link] and it will pass them to rustc when building your
project. Cargo also comes with a built-in test runner which is used to execute unit tests2.

rustup : the Rust toolchain installer and updater. This tool is used to install and update rustc
and cargo when new versions of Rust is released. In addition, rustup can also download
documentation for the standard library. You can have multiple versions of Rust installed at
once and rustup will let you switch between them as needed.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Code Samples in This Training
For this training, we will mostly explore the Rust language through examples which can be executed
through your browser. This makes the setup much easier and ensures a consistent experience for
everyone.

Installing Cargo is still encouraged: it will make it easier for you to do the exercises. On the last day,
we will do a larger exercise which shows you how to work with dependencies and for that you need
Cargo.

The code blocks in this course are fully interactive:

fn main() {
println!("Edit me!");
}

You can use Ctrl + Enter to execute the code when focus is in the text box.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Running Code Locally with Cargo
If you want to experiment with the code on your own system, then you will need to first install Rust.
Do this by following the instructions in the Rust Book. This should give you a working rustc and
cargo . At the time of writing, the latest stable Rust release has these version numbers:

% rustc --version
rustc 1.61.0 (fe5b13d68 2022-05-18)
% cargo --version
cargo 1.61.0 (a028ae4 2022-04-29)

With this is in place, then follow these steps to build a Rust binary from one of the examples in this
training:

1. Click the “Copy to clipboard” button on the example you want to copy.

2. Use cargo new exercise to create a new exercise/ directory for your code:

$ cargo new exercise


Created binary (application) `exercise` package

3. Navigate into exercise/ and use cargo run to build and run your binary:

$ cd exercise
$ cargo run
Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)
Finished dev [unoptimized + debuginfo] target(s) in 0.75s
Running `target/debug/exercise`
Hello, world!

4. Replace the boiler-plate code in src/[Link] with your own code. For example, using the
example on the previous page, make src/[Link] look like

fn main() {
println!("Edit me!");
}

5. Use cargo run to build and run your updated binary:

$ cargo run
Compiling exercise v0.1.0 (/home/mgeisler/tmp/exercise)
Finished dev [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/exercise`
Edit me!

6. Use cargo check to quickly check your project for errors, use cargo build to compile it
without running it. You will find the output in target/debug/ for a normal debug build. Use
cargo build --release to produce an optimized release build in target/release/ .

7. You can add dependencies for your project by editing [Link] . When you run cargo
commands, it will automatically download and compile missing dependencies for you.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Welcome to Day 1
This is the first day of Comprehensive Rust. We will cover a lot of ground today:

Basic Rust syntax: variables, scalar and compound types, enums, structs, references, functions,
and methods.

Memory management: stack vs heap, manual memory management, scope-based memory


management, and garbage collection.

Ownership: move semantics, copying and cloning, borrowing, and lifetimes.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
What is Rust?
Rust is a new programming language which had its 1.0 release in 2015:

Rust is a statically compiled language in a similar role as C++


rustc uses LLVM as its backend.
Rust supports many platforms and architectures:
x86, ARM, WebAssembly, …
Linux, Mac, Windows, …
Rust is used for a wide range of devices:
firmware and boot loaders,
smart displays,
mobile phones,
desktops,
servers.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Hello World!
Let us jump into the simplest possible Rust program, a classic Hello World program:

fn main() {
println!("Hello 🌍!");
}

What you see:

Functions are introduced with fn .


Blocks are delimited by curly braces like in C and C++.
The main function is the entry point of the program.
Rust has hygienic macros, println! is an example of this.
Rust strings are UTF-8 encoded and can contain any Unicode character.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Small Example
Here is a small example program in Rust:

fn main() { // Program entry point


let mut x: i32 = 6; // Mutable variable binding
print!("{x}"); // Macro for printing, like printf
while x != 1 { // No parenthesis around expression
if x % 2 == 0 { // Math like in other languages
x = x / 2;
} else {
x = 3 * x + 1;
}
print!(" -> {x}");
}
println!();
}

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Why Rust?
Some unique selling points of Rust:

Compile time memory safety.


Lack of undefined runtime behavior.
Modern language features.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Compile Time Guarantees
Static memory management at compile time:

No uninitialized variables.
No memory leaks (mostly, see notes).
No double-frees.
No use-after-free.
No NULL pointers.
No forgotten locked mutexes.
No data races between threads.
No iterator invalidation.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Runtime Guarantees
No undefined behavior at runtime:

Array access is bounds checked.


Integer overflow is defined.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Modern Features
Rust is built with all the experience gained in the last 40 years.

Language Features
Enums and pattern matching.
Generics.
No overhead FFI.
Zero-cost abstractions.

Tooling
Great compiler errors.
Built-in dependency manager.
Built-in support for testing.
Excellent Language Server Protocol support.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Basic Syntax
Much of the Rust syntax will be familiar to you from C or C++:

Blocks and scopes are delimited by curly braces.


Line comments are started with // , block comments are delimited by /* ... */ .
Keywords like if and while work the same.
Variable assignment is done with = , comparison is done with == .

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Scalar Types
Types Literals
Signed integers i8 , i16 , i32 , i64 , i128 , isize -10 , 0 , 1_000 , 123i64

Unsigned integers u8 , u16 , u32 , u64 , u128 , usize 0 , 123 , 10u16

Floating point numbers f32 , f64 3.14 , -10.0e20 , 2f32

Strings &str "foo" , r#"\\"#

Unicode scalar values char 'a' , 'α' , '∞'

Byte strings &[u8] b"abc" , br#" " "#

Booleans bool true , false

The types have widths as follows:

iN , uN , and fN are N bits wide,


isize and usize are the width of a pointer,
char is 32 bit wide,
bool is 8 bit wide.

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Compound Types
Types Literals
Arrays [T; N] [20, 30, 40] , [0; 3]

Tuples () , (T,) , (T1, T2) , … () , ('x',) , ('x', 1.2) , …

Array assignment and access:

fn main() {
let mut a: [i8; 10] = [42; 10];
a[5] = 0;
println!("a: {:?}", a);
}

Tuple assignment and access:

fn main() {
let t: (i8, bool) = (7, true);
println!("1st index: {}", t.0);
println!("2nd index: {}", t.1);
}

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
References
Like C++, Rust has references:

fn main() {
let mut x: i32 = 10;
let ref_x: &mut i32 = &mut x;
*ref_x = 20;
println!("x: {x}");
}

Some notes:

We must dereference ref_x when assigning to it, similar to C and C++ pointers.
Rust will auto-dereference in some cases, in particular when invoking methods (try
ref_x.count_ones() ).
References that are declared as mut can be bound to different values over their lifetime.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Dangling References
Rust will statically forbid dangling references:

fn main() {
let ref_x: &i32;
{
let x: i32 = 10;
ref_x = &x;
}
println!("ref_x: {ref_x}");
}

A reference is said to “borrow” the value it refers to.


Rust is tracking the lifetimes of all references to ensure they live long enough.
We will talk more about borrowing when we get to ownership.

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Slices
A slice gives you a view into a larger collection:

fn main() {
let a: [i32; 6] = [10, 20, 30, 40, 50, 60];
println!("a: {a:?}");

let s: &[i32] = &a[2..4];


println!("s: {s:?}");
}

Slices borrow data from the sliced type.


Question: What happens if you modify a[3] ?

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
String vs str
We can now understand the two string types in Rust:

fn main() {
let s1: &str = "World";
println!("s1: {s1}");

let mut s2: String = String::from("Hello ");


println!("s2: {s2}");
s2.push_str(s1);
println!("s2: {s2}");

let s3: &str = &s2[6..];


println!("s3: {s3}");
}

Rust terminology:

&str an immutable reference to a string slice.


String a mutable string buffer.

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Functions
A Rust version of the famous FizzBuzz interview question:

fn main() {
fizzbuzz_to(20); // Defined below, no forward declaration needed
}

fn is_divisible_by(lhs: u32, rhs: u32) -> bool {


if rhs == 0 {
return false; // Corner case, early return
}
lhs % rhs == 0 // The last expression in a block is the return value
}

fn fizzbuzz(n: u32) -> () { // No return value means returning the unit type `()`
match (is_divisible_by(n, 3), is_divisible_by(n, 5)) {
(true, true) => println!("fizzbuzz"),
(true, false) => println!("fizz"),
(false, true) => println!("buzz"),
(false, false) => println!("{n}"),
}
}

fn fizzbuzz_to(n: u32) { // `-> ()` is normally omitted


for i in 1..=n {
fizzbuzz(i);
}
}

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Methods
Rust has methods, they are simply functions that are associated with a particular type. The first
argument of a method is an instance of the type it is associated with:

struct Rectangle {
width: u32,
height: u32,
}

impl Rectangle {
fn area(&self) -> u32 {
[Link] * [Link]
}

fn inc_width(&mut self, delta: u32) {


[Link] += delta;
}
}

fn main() {
let mut rect = Rectangle { width: 10, height: 5 };
println!("old area: {}", [Link]());
rect.inc_width(5);
println!("new area: {}", [Link]());
}

We will look much more at methods in today’s exercise and in tomorrow’s class.

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it
Function Overloading
Overloading is not supported:

Each function has a single implementation:


Always takes a fixed number of parameters.
Always takes a single set of parameter types.
Default values are not supported:
All call sites have the same number of arguments.
Macros are sometimes used as an alternative.

However, function parameters can be generic:

fn pick_one<T>(a: T, b: T) -> T {
if std::process::id() % 2 == 0 { a } else { b }
}

fn main() {
println!("coin toss: {}", pick_one("heads", "tails"));
println!("cash prize: {}", pick_one(500, 1000));
}

Detalles

This site uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic. Learn more Ok, Got it

Common questions

Powered by AI

Integrating Rust with C/C++ projects can pose challenges due to differences in memory management models and build systems. Rust’s strict ownership and borrowing rules may complicate interfacing with C/C++ code that manages memory more freely. Solutions include using Rust’s FFI (Foreign Function Interface) for seamless function calls and employing safe abstractions like Cxx crates to manage unsafe code blocks. These tools enable Rust to complement C/C++ by taking advantage of Rust's safety and concurrency features while maintaining performance .

The ownership model in Rust is fundamental to its memory management strategy. It eliminates common bugs found in languages that permit manual memory management, such as dangling pointers and memory leaks. The ownership model, through concepts like borrowing and lifetimes, enforces strict compile-time checks that ensure valid memory access. This model is key in enabling Rust to provide memory safety guarantees while limiting runtime overhead and allowing for concurrency without data races .

Rustup is important because it manages the Rust toolchain installation and updates, facilitating developers to switch between multiple versions of Rust. It simplifies setting up cross-compilation, installing the rustc compiler and Cargo, and keeping documentation updated. This management makes it easier for developers to maintain environments, ensuring compatibility and access to the latest features and security patches, thereby streamlining the development workflow .

Rust provides several compile-time guarantees such as static memory management, which includes prevention of uninitialized variables, memory leaks, double-frees, use-after-free, NULL pointers, forgotten locked mutexes, and data races between threads. It also ensures no iterator invalidation. These guarantees contribute to software safety by ensuring that common runtime errors associated with manual memory management are avoided or detected at compile time, thereby reducing the risk of undefined behavior at runtime .

Cargo is the Rust dependency manager and build tool. It is significant in the Rust ecosystem for its roles including downloading dependencies from crates.io, managing them, and passing them to rustc during project builds. Cargo also features a built-in test runner for unit testing, which is integral for maintaining code quality and reliability in Rust projects .

Recommended practices for teaching the Comprehensive Rust course include scheduling the four days over two weeks to allow participants to process the information, maintaining a class size of 15-20 for interactive participation, starting with setup early, using mdBook serve for performance, and encouraging participants to work through exercises independently or in small groups. Instructors should address common issues directly and utilize the exercises to reinforce learning .

Rust achieves safety without a garbage collector through its ownership model, which includes borrowing rules and lifetimes to track resource usage at compile time. This eliminates the need for a runtime garbage collector, reducing overhead and enabling predictable performance. The benefits include no need for periodic pauses, better control over memory layout, and deterministic resource deallocation, which makes Rust suitable for low-latency and high-performance applications like game engines and operating systems .

Day 4 of the Comprehensive Rust course covers Android-specific content, focusing on building Android components in Rust, understanding AIDL servers and clients, and achieving interoperability with C, C++, and Java. The content is aimed at writing code for the Android operating system rather than application development. This integration allows leveraging Rust’s safety and performance capabilities in Android development, particularly for system-level programming .

Rust has two primary string types: &str and String. The &str is an immutable reference to a string slice, allowing for lightweight string handling without moving the data. The String type, on the other hand, is a mutable, growable string buffer. This separation allows Rust to offer performance advantages through reduced overhead and flexibility in handling string data. The distinctions in these types provide developers control over memory management and performance optimizations .

The course recommends letting questions drive the exploration of Rust, solving exercises individually or in groups, and using real-time feedback and error resolution. These interactive elements help students engage actively with the material, identify and resolve misunderstandings quickly, and apply concepts in practical scenarios, which enhances retention and understanding of Rust’s paradigms .

You might also like