Types

Boolean

bool

Unsigned integers

u8, u16, u32, u64, u128

Signed Integers

i8, i16, i32, i64, i128

Floating point numbers

f32, f64

Tuple

let coordinates = (1,23);

Array & Slice

// Arrays must have a known length and all
// elements must be initialized
let array = [1, 2, 3, 4, 5];
let array2 = [0; 3]; // [0, 0, 0]
// Unlike arrays the length of a slice is
determined at runtime
let slice = &array[1 .. 3];

Hashmap

use std::collections::HashMap;
let mut subs = HashMap::new();
subs.insert(String::from("LK1"), 15);

Struct

//init
struct User {
   username: String,
   id: i32,
}
//use
let user1 = User {
   username: "Lovis".to_string(),
   id: 11,
}

Enum

// init
enum Command {
   Quit,
   Move { x: i32, y: i32 },
   Speak(String),
   ChangeBGColor(i32, i32, i32),
}
// use
let msg1 = Command::Quit;
let msg2 = Command::Move{ x: 1, y: 2 };
let msg3 = Command::Speak("Hi".to_owned());
let msg4 = Command::ChangeBGColor(0, 0, 0);

Constant

const MAX_POINTS: u32 = 100_000;

Alias

type Punkte = u16;

Mutability

Mutability

let mut x = 0;
x = 1;

Shadowing

let x = 0;
let x = x + 1;

Control flow

if and if let

let num = Some(22);

if num.is_some() {
   println!("{}", num.unwrap());
}

if let Some(i) = num {
   println!("{}", i);
}

loop

let mut c = 0;
loop {
   count += 1;
   if count == 5 {
      break;
   }
}

//nested loops
'outer: loop {
   'inner: loop {
      break;
      break 'outer;
   }
}

returning values from loops

let mut c = 0;
let result = loop {
   c += 1;
   if c == 10 {
      break counter;
   }
}

while and while let

while n < 10 {
   n += 1;
}

let mut optional = Some(10);
while let Some(i) = opional {
   println!("{}", i);
}

for loop

for n in 1..10 {
   println!("n");
}
let names = vec!["Lovis", "pacman"];
for name in names.iter() {
   println!("{name}");
}

match

let optional = Some(10);
match optional {
   Some(i) => println!("{i}"),
   None => println!("No value given"),
}

Ownership / Borrowing

// Simple values which implement the Copytrait are copied by value
let x = 5;
let y = x;
println!("{}", x); // x is still valid
// The string is moved to s2 and s1 is
invalidated
let s1 = String::from("Let's Get Rusty!");
let s2 = s1; // Shallow copy a.k.a move
println!("{}", s1); // Error: s1 is invalid
let s1 = String::from("Let's Get Rusty!");
let s2 = s1.clone(); // Deep copy
// Valid because s1 isn't moved
println!("{}", s1);
fn main() {
   let x = 5;
   takes_copy(x); // x is copied by value
   let s = String::from("Let’s Get Rusty!");
   // s is moved into the function
   takes_ownership(s);
   // return value is moved into s1
   let s1 = gives_ownership();
   let s2 = String::from("LGR");
   let s3 = takes_and_gives_back(s2);
}
fn takes_copy(some_integer: i32) {
   println!("{}", some_integer);
}
fn takes_ownership(some_string: String) {
   println!("{}", some_string);
} // some_string goes out of scope and dropis called. The backing memory is freed.
fn gives_ownership() -> String {
   let some_string = String::from("LGR");
   some_string
}
fn takes_and_gives_back(some_string:
   String) -> String {
   some_string
}

Pattern Matching

let x = 5;
match x {
   // matching literals
   1 => println!("one"),
   // matching multiple patterns
   2 | 3 => println!("two or three"),
   // matching ranges
   4..=9 => println!("within range"),
   // default case (ignores value)
   _ => println!("default")
}

Destructing

struct Point {
   x: i32,
   y: i32,
}
let p = Point { x: 0, y: 7 };
match p {
   Point { x, y: 0 } => {
      println!("{}" , x);
   },
   Point { x, y } => {
      println!("{} {}" , x, y);
   },
}
enum Shape {
   Rectangle { width: i32, height: i32 },
   Circle(i32),
}
let shape = Shape::Circle(10);
match shape {
   Shape::Rectangle { x, y } => //...
   Shape::Circle(radius) => //...
}

Iterators

let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let total: i32 = v1_iter.sum();

// Methods that produce new iterators
let v1: Vec<i32> = vec![1, 2, 3];
let iter = v1.iter().map(|x| x + 1);
// Turning iterators into a collection
let v1: Vec<i32> = vec![1, 2, 3];
let v2: Vec<_> = v1.iter().map(|x| x +1).collect();

Error handeling

// if there is no other option
panic!("Critical Error!");

Option Enum

fn get_user_id(name: &str) -> Option<u32> {
   if database.user_exists(name) {
      return Some(database.get_id(name))
   }
   None
}

Result Enum

fn get_user(id: u32) -> Result<User, Error> {
   if is_logged_in_as(id) {
      return Ok(get_user_object(id))
   }
   Err(Error { msg: "not logged in" })
}

?

fn get_salary(db: Database, id: i32) -> Option<u32> {
   Some(db.get_user(id)?.get_job()?.salary)
}
fn connect(db: Database) ->
   Result<Connection, Error> {
   let conn = db.get_active_instance()?.connect()?;
   Ok(conn)
}

custom Error

type Result<T> = std::result::Result<T,CustomError>;

#[derive(Debug, Clone)]
struct CustomError;

impl fmt::Display for CustomError {
   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      write!(f, "custom error message")
   }
}

Combinators

map

let some_string = Some("lovirent.eu".to_owned());
let some_len = some_string.map(|s| s.len());
struct Error { msg: String }
struct User { name: String }
let string_result: Result<String, Error> = Ok("Lovis".to_owned());
let user_result: Result<User, Error> = string_result.map(|name| {
   User { name }
});