1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-12-03 09:45:17 +02:00

Publish Comprehensive Rust 🦀

This commit is contained in:
Martin Geisler
2022-12-21 16:36:30 +01:00
commit c212a473ba
252 changed files with 8047 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# Default Methods
Traits can implement behavior in terms of other trait methods:
```rust,editable
trait Equals {
fn equal(&self, other: &Self) -> bool;
fn not_equal(&self, other: &Self) -> bool {
!self.equal(other)
}
}
#[derive(Debug)]
struct Centimeter(i16);
impl Equals for Centimeter {
fn equal(&self, other: &Centimeter) -> bool {
self.0 == other.0
}
}
fn main() {
let a = Centimeter(10);
let b = Centimeter(20);
println!("{a:?} equals {b:?}: {}", a.equal(&b));
println!("{a:?} not_equals {b:?}: {}", a.not_equal(&b));
}
```

View File

@@ -0,0 +1,19 @@
# Deriving Traits
You can let the compiler derive a number of traits:
```rust,editable
#[derive(Debug, Clone, PartialEq, Eq, Default)]
struct Player {
name: String,
strength: u8,
hit_points: u8,
}
fn main() {
let p1 = Player::default();
let p2 = p1.clone();
println!("Is {:?}\nequal to {:?}?\nThe answer is {}!", &p1, &p2,
if p1 == p2 { "yes" } else { "no" });
}
```

30
src/traits/drop.md Normal file
View File

@@ -0,0 +1,30 @@
# The `Drop` Trait
Values which implement `Drop` can specify code to run when they go out of scope:
```rust,editable
struct Droppable {
name: &'static str,
}
impl Drop for Droppable {
fn drop(&mut self) {
println!("Dropping {}", self.name);
}
}
fn main() {
let a = Droppable { name: "a" };
{
let b = Droppable { name: "b" };
{
let c = Droppable { name: "c" };
let d = Droppable { name: "d" };
println!("Exiting block B");
}
println!("Exiting block A");
}
drop(a);
println!("Exiting main");
}
```

25
src/traits/from-into.md Normal file
View File

@@ -0,0 +1,25 @@
# `From` and `Into`
Types implement `From` and `Into` to facilitate type conversions:
```rust,editable
fn main() {
let s = String::from("hello");
let addr = std::net::Ipv4Addr::from([127, 0, 0, 1]);
let one = i16::from(true);
let bigger = i32::from(123i16);
println!("{s}, {addr}, {one}, {bigger}");
}
```
`Into` is automatically implemented when `From` is implemented:
```rust,editable
fn main() {
let s: String = "hello".into();
let addr: std::net::Ipv4Addr = [127, 0, 0, 1].into();
let one: i16 = true.into();
let bigger: i32 = 123i16.into();
println!("{s}, {addr}, {one}, {bigger}");
}
```

View File

@@ -0,0 +1,9 @@
# Important Traits
We will now look at some of the most common traits of the Rust standard library:
* `Iterator` and `IntoIterator` used in `for` loops,
* `From` and `Into` used to convert values,
* `Read` and `Write` used for IO,
* `Add`, `Mul`, ... used for operator overloading, and
* `Drop` used for defining destructors.

28
src/traits/iterator.md Normal file
View File

@@ -0,0 +1,28 @@
# Iterators
You can implement the `Iterator` trait on your own types:
```rust,editable
struct Fibonacci {
curr: u32,
next: u32,
}
impl Iterator for Fibonacci {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
let new_next = self.curr + self.next;
self.curr = self.next;
self.next = new_next;
Some(self.curr)
}
}
fn main() {
let fib = Fibonacci { curr: 0, next: 1 };
for (i, n) in fib.enumerate().take(5) {
println!("fib({i}): {n}");
}
}
```

22
src/traits/operators.md Normal file
View File

@@ -0,0 +1,22 @@
# `Add`, `Mul`, ...
Operator overloading is implemented via traits in `std::ops`:
```rust,editable
#[derive(Debug, Copy, Clone)]
struct Point { x: i32, y: i32 }
impl std::ops::Add for Point {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {x: self.x + other.x, y: self.y + other.y}
}
}
fn main() {
let p1 = Point { x: 10, y: 20 };
let p2 = Point { x: 100, y: 200 };
println!("{:?} + {:?} = {:?}", p1, p2, p1 + p2);
}
```

40
src/traits/read-write.md Normal file
View File

@@ -0,0 +1,40 @@
# `Read` and `Write`
Using `Read` and `BufRead`, you can abstract over `u8` sources:
```rust,editable
use std::io::{BufRead, BufReader, Read, Result};
fn count_lines<R: Read>(reader: R) -> usize {
let buf_reader = BufReader::new(reader);
buf_reader.lines().count()
}
fn main() -> Result<()> {
let slice: &[u8] = b"foo\nbar\nbaz\n";
println!("lines in slice: {}", count_lines(slice));
let file = std::fs::File::open(std::env::current_exe()?)?;
println!("lines in file: {}", count_lines(file));
Ok(())
}
```
Similarly, `Write` lets you abstract over `u8` sinks:
```rust,editable
use std::io::{Result, Write};
fn log<W: Write>(writer: &mut W, msg: &str) -> Result<()> {
writer.write_all(msg.as_bytes())?;
writer.write_all("\n".as_bytes())
}
fn main() -> Result<()> {
let mut buffer = Vec::with_capacity(1024);
log(&mut buffer, "Hello")?;
log(&mut buffer, "World")?;
println!("Logged: {:?}", buffer);
Ok(())
}
```