You've already forked comprehensive-rust
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:
28
src/traits/default-methods.md
Normal file
28
src/traits/default-methods.md
Normal 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));
|
||||
}
|
||||
```
|
||||
19
src/traits/deriving-traits.md
Normal file
19
src/traits/deriving-traits.md
Normal 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
30
src/traits/drop.md
Normal 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
25
src/traits/from-into.md
Normal 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}");
|
||||
}
|
||||
```
|
||||
9
src/traits/important-traits.md
Normal file
9
src/traits/important-traits.md
Normal 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
28
src/traits/iterator.md
Normal 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
22
src/traits/operators.md
Normal 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
40
src/traits/read-write.md
Normal 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(())
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user