You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-06-23 01:07:40 +02:00
Publish Comprehensive Rust 🦀
This commit is contained in:
.gitignoreCONTRIBUTING.mdCargo.tomlLICENSE.txtREADME.mdbook.tomlga4.jsrustfmt.toml
src
SUMMARY.mdandroid.mdgenerics.md
android
aidl.md
basic-syntax.mdaidl
bpfmt.shbuild-rules.mdbuild-rules
build_all.shinteroperability.mdinteroperability
logging.mdlogging
setup.mdbasic-syntax
compound-types.mdfunctions-interlude.mdfunctions.mdmethods.mdreferences-dangling.mdreferences.mdscalar-types.mdscopes-shadowing.mdslices.mdstatic-and-const.mdstring-slices.mdtype-inference.mdvariables.md
cargo.mdcargo
concurrency.mdconcurrency
control-flow.mdcontrol-flow
blocks.mdbreak-continue.mdfor-expressions.mdif-expressions.mdif-let-expressions.mdloop-expressions.mdmatch-expressions.mdwhile-expressions.mdwhile-let-expressions.md
credits.mdenums.mdenums
error-handling.mderror-handling
converting-error-types.mdderiving-error-enums.mderror-contexts.mdpanic-unwind.mdpanics.mdresult.mdtry-operator.md
exercises
day-1
afternoon.mdbook-library.mdbook-library.rsfor-loops.mdfor-loops.rsimplicit-conversions.mditerators-and-ownership.mdmorning.mdsolutions-afternoon.mdsolutions-morning.md
day-2
afternoon.mdhealth-statistics.mdluhn.mdluhn.rsmorning.mdpoints-polygons.mdpoints-polygons.rssolutions-afternoon.mdsolutions-morning.mdstrings-iterators.mdstrings-iterators.rs
day-3
afternoon.mdmorning.mdsafe-ffi-wrapper.mdsafe-ffi-wrapper.rssimple-gui.mdsimple-gui.rssolutions-afternoon.mdsolutions-morning.md
day-4
afternoon.mddining-philosophers.mddining-philosophers.rslink-checker.mdlink-checker.rsmorning.mdsolutions-morning.md
solutions.mdgenerics
hello-world.mdhello-world
memory-management.mdmemory-management
methods.mdmethods
modules.mdmodules
other-resources.mdownership.mdownership
borrowing.mdcopy-clone.mddouble-free-modern-cpp.mdlifetimes-data-structures.mdlifetimes-function-calls.mdlifetimes.mdmove-semantics.mdmoved-strings-rust.mdmoves-function-calls.mdshared-unique-borrows.md
pattern-matching.mdpattern-matching
std.mdstd
structs.mdstructs
structure.mdtesting.mdtesting
thanks.mdtraits.mdtraits
default-methods.mdderiving-traits.mddrop.mdfrom-into.mdimportant-traits.mditerator.mdoperators.mdread-write.md
unsafe.mdunsafe
welcome-day-1.mdwelcome-day-1
welcome-day-2.mdwelcome-day-3.mdwelcome-day-4.mdwelcome.mdwhy-rust.mdwhy-rust
third_party
26
src/basic-syntax/compound-types.md
Normal file
26
src/basic-syntax/compound-types.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Compound Types
|
||||
|
||||
| | Types | Literals |
|
||||
|--------|---------------------|--------------------------|
|
||||
| Arrays | `[T; N]` | `[20, 30, 40]`, `[0; 3]` |
|
||||
| Tuples | `(T1, T2, T3, ...)` | `('x', 1.2, 0)` |
|
||||
|
||||
Array assignment and access:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let mut a: [i8; 10] = [42; 10];
|
||||
a[5] = 0;
|
||||
println!("a: {:?}", a);
|
||||
}
|
||||
```
|
||||
|
||||
Tuple assignment and access:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let t: (i8, bool) = (7, true);
|
||||
println!("1st index: {}", t.0);
|
||||
println!("2nd index: {}", t.1);
|
||||
}
|
||||
```
|
23
src/basic-syntax/functions-interlude.md
Normal file
23
src/basic-syntax/functions-interlude.md
Normal file
@ -0,0 +1,23 @@
|
||||
# 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:
|
||||
|
||||
```rust,editable
|
||||
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));
|
||||
}
|
||||
```
|
31
src/basic-syntax/functions.md
Normal file
31
src/basic-syntax/functions.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Functions
|
||||
|
||||
A Rust version of the famous FizzBuzz interview question:
|
||||
|
||||
```rust,editable
|
||||
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 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 n in 1..=n {
|
||||
fizzbuzz(n);
|
||||
}
|
||||
}
|
||||
```
|
30
src/basic-syntax/methods.md
Normal file
30
src/basic-syntax/methods.md
Normal file
@ -0,0 +1,30 @@
|
||||
# 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:
|
||||
|
||||
```rust,editable
|
||||
struct Rectangle {
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
impl Rectangle {
|
||||
fn area(&self) -> u32 {
|
||||
self.width * self.height
|
||||
}
|
||||
|
||||
fn inc_width(&mut self, delta: u32) {
|
||||
self.width += delta;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut rect = Rectangle { width: 10, height: 5 };
|
||||
println!("old area: {}", rect.area());
|
||||
rect.inc_width(5);
|
||||
println!("new area: {}", rect.area());
|
||||
}
|
||||
```
|
||||
|
||||
* We will look much more at methods in today's exercise and in tomorrow's class.
|
19
src/basic-syntax/references-dangling.md
Normal file
19
src/basic-syntax/references-dangling.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Dangling References
|
||||
|
||||
Rust will statically forbid dangling references:
|
||||
|
||||
```rust,editable,compile_fail
|
||||
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 is 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.
|
18
src/basic-syntax/references.md
Normal file
18
src/basic-syntax/references.md
Normal file
@ -0,0 +1,18 @@
|
||||
# References
|
||||
|
||||
Like C++, Rust has references:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let mut x: i32 = 10;
|
||||
let ref_x: &mut i32 = &mut x;
|
||||
*ref_x = 20;
|
||||
println!("x: {x}");
|
||||
}
|
||||
```
|
||||
|
||||
Some differences from C++:
|
||||
|
||||
* We must dereference `ref_x` when assigning to it, similar to C pointers,
|
||||
* Rust will auto-dereference in some cases, in particular when invoking
|
||||
methods (try `count_ones`).
|
18
src/basic-syntax/scalar-types.md
Normal file
18
src/basic-syntax/scalar-types.md
Normal file
@ -0,0 +1,18 @@
|
||||
# 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.
|
21
src/basic-syntax/scopes-shadowing.md
Normal file
21
src/basic-syntax/scopes-shadowing.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Scopes and Shadowing
|
||||
|
||||
You can shadow variables, both those from outer scopes and variables from the
|
||||
same scope:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let a = 10;
|
||||
println!("before: {a}");
|
||||
|
||||
{
|
||||
let a = "hello";
|
||||
println!("inner scope: {a}");
|
||||
|
||||
let a = true;
|
||||
println!("shadowed in inner scope: {a}");
|
||||
}
|
||||
|
||||
println!("after: {a}");
|
||||
}
|
||||
```
|
16
src/basic-syntax/slices.md
Normal file
16
src/basic-syntax/slices.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Slices
|
||||
|
||||
A slice gives you a view into a larger collection:
|
||||
|
||||
```rust,editable
|
||||
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]`?
|
39
src/basic-syntax/static-and-const.md
Normal file
39
src/basic-syntax/static-and-const.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Static and Constant Variables
|
||||
|
||||
Global state is managed with static and constant variables
|
||||
|
||||
## `const`
|
||||
|
||||
You can declare compile-time constants:
|
||||
|
||||
```rust,editable
|
||||
const DIGEST_SIZE: usize = 3;
|
||||
const ZERO: Option<u8> = Some(42);
|
||||
|
||||
fn compute_digest(text: &str) -> [u8; DIGEST_SIZE] {
|
||||
let mut digest = [ZERO.unwrap_or(0); DIGEST_SIZE];
|
||||
for (idx, &b) in text.as_bytes().iter().enumerate() {
|
||||
digest[idx % DIGEST_SIZE] = digest[idx % DIGEST_SIZE].wrapping_add(b);
|
||||
}
|
||||
digest
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let digest = compute_digest("Hello");
|
||||
println!("Digest: {digest:?}");
|
||||
}
|
||||
```
|
||||
|
||||
## `static`
|
||||
|
||||
You can also declare static variables:
|
||||
|
||||
```rust,editable
|
||||
static BANNER: &str = "Welcome to RustOS 3.14";
|
||||
|
||||
fn main() {
|
||||
println!("{BANNER}");
|
||||
}
|
||||
```
|
||||
|
||||
We will look at mutating static data in the chapter on Unsafe Rust.
|
20
src/basic-syntax/string-slices.md
Normal file
20
src/basic-syntax/string-slices.md
Normal file
@ -0,0 +1,20 @@
|
||||
# `String` vs `str`
|
||||
|
||||
We can now understand the two string types in Rust:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let s1: &str = "Hello";
|
||||
println!("s1: {s1}");
|
||||
|
||||
let mut s2: String = String::from("Hello ");
|
||||
println!("s2: {s2}");
|
||||
s2.push_str(s1);
|
||||
println!("s2: {s2}");
|
||||
}
|
||||
```
|
||||
|
||||
Rust terminology:
|
||||
|
||||
* `&str` an immutable reference to a string slice.
|
||||
* `String` a mutable string buffer
|
22
src/basic-syntax/type-inference.md
Normal file
22
src/basic-syntax/type-inference.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Type Inference
|
||||
|
||||
Rust will look at how the variable is _used_ to determine the type:
|
||||
|
||||
```rust,editable
|
||||
fn takes_u32(x: u32) {
|
||||
println!("u32: {x}");
|
||||
}
|
||||
|
||||
fn takes_i8(y: i8) {
|
||||
println!("i8: {y}");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 10;
|
||||
let y = 20;
|
||||
|
||||
takes_u32(x);
|
||||
takes_i8(y);
|
||||
// takes_u32(y);
|
||||
}
|
||||
```
|
13
src/basic-syntax/variables.md
Normal file
13
src/basic-syntax/variables.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Variables
|
||||
|
||||
Rust provides type safety via static typing. Variable bindings are immutable by
|
||||
default:
|
||||
|
||||
```rust,editable
|
||||
fn main() {
|
||||
let x: i32 = 10;
|
||||
println!("x: {x}");
|
||||
// x = 20;
|
||||
// println!("x: {x}");
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user