Image

Rust Basics

Setup new project or initialize in existing folder:

cargo new <project_dir>
cargo init

Core rust commands

cargo build # Compiles the program and produces an executable
cargo run # Compiles, produces executable and runs the program all in one
cargo check # Compiles the program ONLY but does not produce executable
cargo build --release # Builds an optimized release version
cargo doc --open # Build doc of all dependencies in the project and opens it in the local browser

Rust Language basics

let immutable_variable // All variables in Rust are immutable
let mut mutable_variable // Adding "mut" makes variable mutable
&variable // Reference: allows access and manipulation of data in memory without additional memory copying.
let variable: u32 // Adding ":" after variale means to annotate the type (e.g. u32, insigned 32-bit integer)
Err(_) // "_" is a catch-all value. E.g. Err(_) matches all error values.
Result // A "promise-like" output that has variants "Ok" or "Err". Results should be handled by a .expect() method, which passes the "Ok" but sends a warning in the case of "Err",

Char literal vs. string literal

There is a difference between single quotes ' and double quotes " , the former denotes a char literal whereas the other denotes &str. Note that string literal is different from the String data-type.

Statements and Expressions

Rust is an expression-based language. This is in contrast to statement-based language.

  • Statements are instructions that perform some action and do not return a value
  • Expressions evaluate to a resultant value. Expressions do not include ending semicolons - adding semicolon turns it into a statement

If blocks

if statements must always be a boolean - you cannot use a number, as you can in JavaScript, that will implicitly convert it to a bool, in Rust you must be explicit. The syntax of Rust if statements are as follows:

if condition {
	println!("Condition is true!");
} else if another_condition {
	println!("Another condition is true, but it will not fire if the first condition has already fired!");
} else {
	println!("Whatever...");
}

// can also do this for variale initialization
let number = if condition { 5 } else { 6 };
// in the above case, all options of the branch must evaluate to the same type

Loops

Normally, break and continue operate from the innermost loop in the case of multiple or nested loops. But in Rust you can label loops to control which loops to manipulate. Loop labels must begin with a single quote followed by a colon after the label and then the loop operator.

let mut count = 0;
'counting_up: loop {
	let mut remaining = 10;
	loop {
		if remaining == 9 {
			break;
		}
		if count == 2 {
			break 'counting_up;
		}
		remaining -= 1;
	}

	count += 1;
}
println!("End count = {count}");

When running through the index of an array, it is crucial that the condition matches the exact number of elements in an array. This approach is error prone since changing one side will not change the other, opening a vulnerability. To address this, use a for loop.

let a = [10, 20, 30, 40, 50];
for element in a {
	println!("the value is: {element}");
}

Alternatively, if you need to control the amount of loops, you can use a rev method.

for number in (1..4).rev() {
	println!("{number}!");
}
println!("LIFTOFF!!!");

Compound Types

Tuple: A fixed group of varying data-types

let tup: (i32, f64, u8) = (500, 6.4, 1);

Array: A fixed group of same-kind data-types

let a: [i32; 5] = [1, 2, 3, 4, 5];

Copying Unknown Runtime Values

When the value is not known at compile time, Rust will use the heap to store data. Normally, when one “copies” one such variable to another, it won’t actually copy the data but move the pointer from the first variable to the second. In order to copy the values of a runtime variable stored on the heap, use the .clone() method.

© Filip Niklas 2024. All poetry rights reserved. Permission is hereby granted to freely copy and use notes about programming and any code.