Populate
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/target
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "comprehensive_rust"
|
||||
version = "0.1.0"
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
[package]
|
||||
name = "comprehensive_rust"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
[[bin]]
|
||||
name = "move-semantics"
|
||||
path = "src/move-semantics.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "moves-in-function-calls"
|
||||
path = "src/moves-in-function-calls.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "copying"
|
||||
path = "src/copying.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "lifetimes-function-calls"
|
||||
path = "src/lifetimes-function-calls.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "lifetimes-structs"
|
||||
path = "src/lifetimes-structs.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "library"
|
||||
path = "src/exercises/library.rs"
|
||||
@@ -0,0 +1,17 @@
|
||||
// https://google.github.io/comprehensive-rust/ownership/copy-clone.html
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct Point(i32, i32);
|
||||
|
||||
fn main() {
|
||||
// Copied by default
|
||||
let x = 42;
|
||||
let y = x;
|
||||
println!("x: {x}");
|
||||
println!("y: {y}");
|
||||
|
||||
// implements the Copy trait
|
||||
let p1 = Point(3, 4);
|
||||
let p2 = p1;
|
||||
println!("p1: {p1:?}");
|
||||
println!("p2: {p2:?}");
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// https://google.github.io/comprehensive-rust/exercises/day-1/iterators-and-ownership.html
|
||||
|
||||
|
||||
// Traits are like interfaces: they describe behavior (methods) for a type. The Iterator trait
|
||||
// simply says that you can call next until you get None back:
|
||||
// pub trait Iterator {
|
||||
// type Item;
|
||||
// fn next(&mut self) -> Option<Self::Item>;
|
||||
// }
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// https://google.github.io/comprehensive-rust/exercises/day-1/book-library.html
|
||||
struct Library {
|
||||
books: Vec<Book>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Book {
|
||||
title: String,
|
||||
year: u16,
|
||||
}
|
||||
|
||||
impl Book {
|
||||
// This is a constructor, used below.
|
||||
fn new(title: &str, year: u16) -> Book {
|
||||
Book {
|
||||
title: String::from(title),
|
||||
year,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This makes it possible to print Book values with {}.
|
||||
impl std::fmt::Display for Book {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} ({})", self.title, self.year)
|
||||
}
|
||||
}
|
||||
|
||||
impl Library {
|
||||
fn new() -> Library {
|
||||
Library {
|
||||
books: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
fn len(self) -> usize {
|
||||
self.books.len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.books.len() == 0
|
||||
}
|
||||
|
||||
fn add_book(&mut self, book: Book) {
|
||||
self.books.push(book)
|
||||
}
|
||||
|
||||
fn print_books(&self) {
|
||||
for book in self.books.iter() {
|
||||
println!("book: {book}");
|
||||
}
|
||||
}
|
||||
|
||||
fn oldest_book(&self) -> Option<&Book> {
|
||||
let mut oldest : Option<&Book> = None;
|
||||
for book in self.books.iter() {
|
||||
if oldest.is_none() {
|
||||
oldest = Option::from(book)
|
||||
} else if book.year < oldest.unwrap().year {
|
||||
oldest = Option::from(book)
|
||||
}
|
||||
}
|
||||
|
||||
oldest
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// This shows the desired behavior. Uncomment the code below and
|
||||
// implement the missing methods. You will need to update the
|
||||
// method signatures, including the "self" parameter!
|
||||
let mut library = Library::new();
|
||||
|
||||
println!("Our library is empty: {}", library.is_empty());
|
||||
|
||||
library.add_book(Book::new("Lord of the Rings", 1954));
|
||||
library.add_book(Book::new("Alice's Adventures in Wonderland", 1865));
|
||||
|
||||
library.print_books();
|
||||
|
||||
match library.oldest_book() {
|
||||
Some(book) => println!("My oldest book is {book}"),
|
||||
None => println!("My library is empty!"),
|
||||
}
|
||||
|
||||
println!("Our library has {} books", library.len());
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// https://google.github.io/comprehensive-rust/ownership/lifetimes-function-calls.html
|
||||
#[derive(Debug)]
|
||||
struct Point(i32, i32);
|
||||
|
||||
// 'a is a generic parameter, it is inferred by the compiler.
|
||||
// Lifetimes start with ' and 'a is a typical default name.
|
||||
// Read &'a Point as “a borrowed Point which is valid for at least the lifetime a”.
|
||||
// The at least part is important when parameters are in different scopes.
|
||||
fn left_most<'a>(p1: &'a Point, p2: &'a Point) -> &'a Point {
|
||||
if p1.0 < p2.0 { p1 } else { p2 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p1: Point = Point(10, 10);
|
||||
let p2: Point = Point(20, 20); // Put into different scope
|
||||
let p3: &Point = left_most(&p1, &p2);
|
||||
println!("left-most point: {:?}", p3);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// https://google.github.io/comprehensive-rust/ownership/lifetimes-data-structures.html
|
||||
//
|
||||
// If a data type stores borrowed data, it must be annotated with a lifetime:
|
||||
#[derive(Debug)]
|
||||
struct Highlight<'doc>(&'doc str);
|
||||
|
||||
fn erase(text: String) {
|
||||
println!("Bye {text}!");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let text = String::from("The quick brown fox jumps over the lazy dog.");
|
||||
let fox = Highlight(&text[4..19]);
|
||||
let dog = Highlight(&text[35..43]);
|
||||
// erase(text);
|
||||
println!("{fox:?}");
|
||||
println!("{dog:?}");
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// https://google.github.io/comprehensive-rust/ownership/move-semantics.html
|
||||
fn main() {
|
||||
let s1: String = String::from("Hello!");
|
||||
let s2: String = s1;
|
||||
println!("s2: {s2}");
|
||||
// println!("s1: {s1}");
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// https://google.github.io/comprehensive-rust/ownership/moves-function-calls.html
|
||||
fn say_hello(name: String) {
|
||||
println!("Hello {name}")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let name = String::from("Alice");
|
||||
say_hello(name);
|
||||
// say_hello(name);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
let triple = [0, -2, 3];
|
||||
println!("Tell me about {triple:?}");
|
||||
match triple {
|
||||
[0, y, z] => println!("First is 0, y = {y}, and z = {z}"),
|
||||
[1, ..] => println!("First is 1 and the rest were ignored"),
|
||||
_ => println!("All elements were ignored"),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
enum Result {
|
||||
Ok(i32),
|
||||
Err(String),
|
||||
}
|
||||
|
||||
fn divide_in_two(n: i32) -> Result {
|
||||
if n % 2 == 0 {
|
||||
Result::Ok(n / 2)
|
||||
} else {
|
||||
Result::Err(format!("cannot divide {} into two equal parts", n))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut n = 100;
|
||||
match divide_in_two(n) {
|
||||
Result::Ok(half) => println!("{n} divided in two is {half}"),
|
||||
Result::Err(msg) => println!("sorry, an error happened: {msg}"),
|
||||
}
|
||||
|
||||
n = 105;
|
||||
match divide_in_two(n) {
|
||||
Result::Ok(half) => println!("{n} divided in two is {half}"),
|
||||
Result::Err(msg) => println!("sorry, an error happened: {msg}"),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
struct Foo {
|
||||
x: (u32, u32),
|
||||
y: u32,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
let foo = Foo { x: (1, 2), y: 3 };
|
||||
match foo {
|
||||
Foo { x: (1, b), y } => println!("x.0 = 1, b = {b}, y = {y}"),
|
||||
Foo { y: 2, x: i } => println!("y = 2, i = {i:?}"),
|
||||
Foo { y, .. } => println!("y = {y}, other fields were ignored"),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use std::mem::{align_of, size_of};
|
||||
|
||||
macro_rules! dbg_size {
|
||||
($t:ty) => {
|
||||
println!("{}: size {} bytes, align: {} bytes",
|
||||
stringify!($t), size_of::<$t>(), align_of::<$t>());
|
||||
};
|
||||
}
|
||||
|
||||
enum Foo {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// adding a variang-payload will change the size :)
|
||||
dbg_size!(Foo);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
fn generate_random_number() -> i32 {
|
||||
4 // Chosen by fair dice roll. Guaranteed to be random.
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CoinFlip {
|
||||
Heads,
|
||||
Tails,
|
||||
}
|
||||
|
||||
fn flip_coin() -> CoinFlip {
|
||||
let random_number = generate_random_number();
|
||||
if random_number % 2 == 0 {
|
||||
return CoinFlip::Heads;
|
||||
} else {
|
||||
return CoinFlip::Tails;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("You got: {:?}", flip_coin());
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// https://google.github.io/comprehensive-rust/structs/field-shorthand.html
|
||||
// If you already have variables with the right names, then you can create the struct using a shorthand:
|
||||
#[derive(Debug)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
}
|
||||
|
||||
impl Person {
|
||||
fn new(name: String, age: u8) -> Person {
|
||||
Person { name, age }
|
||||
}
|
||||
|
||||
// This WONT compile:
|
||||
// fn newBad(nameBad: String, ageBad: u8) -> Person {
|
||||
// Person { nameBad, ageBad }
|
||||
// }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let peter = Person::new(String::from("Peter"), 27);
|
||||
println!("{peter:?}");
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// When matching, you can add a guard to a pattern. This is an arbitrary Boolean expression which will be executed if the pattern matches:
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
let pair = (2, -2);
|
||||
println!("Tell me about {pair:?}");
|
||||
match pair {
|
||||
(x, y) if x == y => println!("These are twins"),
|
||||
(x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
|
||||
(x, _) if x % 2 == 1 => println!("The first one is odd"),
|
||||
_ => println!("No correlation..."),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#[derive(Debug)]
|
||||
struct Person {
|
||||
name : String,
|
||||
age: u8,
|
||||
}
|
||||
|
||||
impl Person {
|
||||
fn say_hello(&self) {
|
||||
println!("Hello my name is {}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let christian = Person {
|
||||
name : String::from("Christian"),
|
||||
age: 25,
|
||||
};
|
||||
christian.say_hello()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fn main() {
|
||||
let input = 'x';
|
||||
|
||||
match input {
|
||||
'q' => println!("Quitting"),
|
||||
'a' | 's' | 'w' | 'd' => println!("Moving around"),
|
||||
'0'..='9' => println!("Number input"),
|
||||
_ => println!("Something else"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// https://google.github.io/comprehensive-rust/methods/example.html
|
||||
//
|
||||
// The &self below indicates that the method borrows the object immutably. There are other possible receivers for a method:
|
||||
//
|
||||
// * &self: borrows the object from the caller using a shared and immutable reference. The object can be used again afterwards.
|
||||
// * &mut self: borrows the object from the caller using a unique and mutable reference. The object can be used again afterwards.
|
||||
// * self: takes ownership of the object and moves it away from the caller. The method becomes the owner of the object. The object will be drop (deallocated) when the method returns, unless it’s ownership is explicitly transmitted.
|
||||
// * No receiver: this becomes a static method on the struct. Typically used to create constructors which are called new by convention.
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Race {
|
||||
name: String,
|
||||
laps: Vec<i32>,
|
||||
}
|
||||
|
||||
impl Race {
|
||||
fn new(name: &str) -> Race { // No receiver, a static method
|
||||
Race { name: String::from(name), laps: Vec::new() }
|
||||
}
|
||||
|
||||
fn add_lap(&mut self, lap: i32) { // Exclusive borrowed read-write access to self
|
||||
self.laps.push(lap);
|
||||
}
|
||||
|
||||
fn print_laps(&self) { // Shared and read-only borrowed access to self
|
||||
println!("Recorded {} laps for {}:", self.laps.len(), self.name);
|
||||
for (idx, lap) in self.laps.iter().enumerate() {
|
||||
println!("Lap {idx}: {lap} sec");
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(self) { // Exclusive ownership of self
|
||||
let total = self.laps.iter().sum::<i32>();
|
||||
println!("Race {} is finished, total lap time: {}", self.name, total);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut race = Race::new("Monaco Grand Prix");
|
||||
race.add_lap(70);
|
||||
race.add_lap(68);
|
||||
race.print_laps();
|
||||
race.add_lap(71);
|
||||
race.print_laps();
|
||||
race.finish();
|
||||
|
||||
// using `race` after here is invalid since ownership was moved to the finish method
|
||||
//
|
||||
// race.print_laps()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// https://google.github.io/comprehensive-rust/structs.html
|
||||
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let peter = Person {
|
||||
name: String::from("Christian"),
|
||||
age: 25,
|
||||
};
|
||||
|
||||
println!("{} is {} years old", peter.name, peter.age);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// If the field names are unimportant, you can use a tuple struct:
|
||||
struct Point(i32, i32);
|
||||
|
||||
// This is often used for single-field wrappers (called newtypes).
|
||||
// Single-field wrappers are similar to type-aliases from Golang.
|
||||
#[derive(Debug)]
|
||||
struct Newtons(f64);
|
||||
|
||||
fn compute_thruster_force() -> Newtons {
|
||||
todo!("Ask a rocket scientist at NASA")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let p = Point(17, 23);
|
||||
println!("({}, {})", p.0, p.1);
|
||||
|
||||
let force = compute_thruster_force();
|
||||
println!("{:?}", force)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
enum WebEvent {
|
||||
PageLoad, // Variant without payload
|
||||
KeyPress(char), // Tuple struct variant
|
||||
Click { x: i64, y: i64 }, // Full struct variant
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn inspect(event: WebEvent) {
|
||||
match event {
|
||||
WebEvent::PageLoad => println!("page loaded"),
|
||||
WebEvent::KeyPress(c) => println!("pressed '{c}'"),
|
||||
WebEvent::Click { x, y } => println!("clicked at x={x}, y={y}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let load = WebEvent::PageLoad;
|
||||
let press = WebEvent::KeyPress('x');
|
||||
let click = WebEvent::Click { x: 20, y: 80 };
|
||||
|
||||
inspect(load);
|
||||
inspect(press);
|
||||
inspect(click);
|
||||
}
|
||||
Reference in New Issue
Block a user