Rust is one of most beloved and important languages in the world. It is a programming language focused on memory safety, protection, high performance during the processing of large amounts of data, concurrency and a highly efficient compiler.
Over 300 of the biggest companies in the world reportedly use Rust in their tech stacks, including Dropbox, Sentry, and Brilliant. Rust is mostly used if you’re looking for work in project types as Web Development, Systems Programming, and CLI Tools
Why is this the right Rust course for you?
This is the most complete Rust focused course on Udemy. It’s an all-in-one topic by topic focused approach that will take you from the very fundamentals of Rust and programming, all the way to complex concepts such as multi threading and error handling.
You will learn Rust from the very beginning, step-by-step. I will guide you through building programs from scratch and fun code along with examples, an important theory about how Rust works behind the scenes, and compiling and deploying your own programs from basic geometric calculations to spawning threads and manipulating the multi process level coding.
You will also learn how to problem solve like a developer, how to build programs scratch, the proper conventions for your code, how to debug code, and many other real-world skills that you will need on your developer job.
And unlike other courses, this one actually contains beginner, intermediate, advanced, and even expert topics, so you don’t have to buy any other course in order to master Rust from the ground up!
But… You don’t have to go into all these topics. This is a long course that focuses purely on Rust, because, after all, it’s “The Complete Rust Course”. It is designed to bring you a combination of courses all in one! But you can enhance your skill level by only watching sections of this course. You can use this course as the lifetime reference guide for certain topics as you continue to build projects and learn more that you can always come back to anytime you wish to advance in a particular topic.
By the end of the course, you will have the knowledge and confidence that you need in order to ace your Rust job interviews and become a developer for programming in Rust.
Why am I the right Rust teacher for you?
My name is Clarian, I’ve worked as a head engineer and and am fully passionate and dedicated to what I teach. I have worked and built with top SF Valley companies and blockchain from NEAR to Solana consulting including working on projects that use Rust for coding out smart contracts. Problem-solving and building complex design projects is my love and my life. I am someone who is passionate and committed to building quality projects from the ground up.
I have recently been spending my time building comprehensive training models with clear explanations to help others evolve and grow the space. This is the most clearly focused and in-depth solidity course that you will find on Udemy (and maybe the entire internet) that provides video code alongs, plenty of challenges, and exercises with solutions and discussions combined into one.
I know how students learn Rust and what they need in order to master it. And with that knowledge, I designed the ideal course curriculum. It’s a focused approach on core fundamentals, multiple real world examples, advanced pattern techniques and hands on projects, that will take you from zero to professional and confident Rust developer in a matter of weeks.
What do we learn exactly in this course?
- Build multiple complex programs from scratch for your portfolio! In these projects, you will learn how to think and properly develop your ideas into written code including how to maximize your time by finding and reading documentation and best practices.
- Master the Rust fundamentals: variables, if/else, operators, boolean logic, String Object, functions, arrays, modifiers, macros, loops, strings, vectors, object handling, concurrency, memory allocation, stack vs the heap and more
- Learn Rust from the beginning: Public & Private visibility (correctly securing data), struct and enums, special macros and variables, functions, hashMaps etc
- How Rust works behind the scenes: Memory safety and data races (low level language), events and error handling, scoping, threading and much more
- Deep dive into functions: functions, methods, closures, recursion, main function and more
- Deep dive into object-oriented programming: Structs and Enum building from scratch, GenericTypes and Traits for libraries and modules and much more. Even though structs and enums with methods aren’t called objects, they provide the same functionality, according to the Gang of Four’s definition of objects.
- Learn the Rust techniques that are used by professionals including concretion version abstractions and interface design, the cargo tool, IDE, debugging and compiling.
Check out the course curriculum for an even more detailed overview of the content 🙂
This is what’s also included in the package:
- Downloadable code files you can reference whenever you want.
- Clear explanations which come with exercises, solutions, and discussions
- An online community of active developers and students is available for support and discussion.
- Free support in the course Q&A
- 30+ Exercises to practice your new skills (solutions included)
This course is for you if…
- … you want to gain a clear and advanced understanding of Rust
- … you have been trying to learn Rust but: 1) still don’t really understand Rust, or 2) still don’t feel confident to write programs in the language
- … you are interested in working on a Rust based project in the future
- … you already know Rust and are looking for a course to clearly go over advanced topics. This course includes expert topics!
- … you want to get started with programming: Rust is an awesome and very interesting first language!
Does any of the above sound good to you? If so, then whenever you’re ready, start this new adventure today, and join me and thousands of other developers in the most focused Rust course that you will ever need!
This Rust course is ideal for anyone searching for more info on the following: Rust – systems programming – concurrency – web developer – Rust interview preparation.
Rust Course Set Up
-
1What Is Rust And Why It Matters - Quick Overview
-
2Join Our Online Live School
-
3What Is Rust Concurrency
-
4Rust's Growth in Popularity
-
5Rust - The Borrow Checker
-
6Safe Mode and Unsafe Mode in Rust
-
7Data Races in Rust
-
8Issues with Rust
-
9What Is Rust - Summary
-
10Exercise - Meet The Online Community
Beginner Lessons in Rust
Beginner To Intermediate Lessons
-
15How To Write Comments in Rust
-
16First Exercise Solution on How To Write Comments in Rust
/*
Comments - comments explain the code
Any program requires comments, and Rust supports a few different varieties:
Regular comments which are ignored by the compiler:
//: double line comments which go to the end of a line
/* */: Block comments go to the closing delimiter
///: Doc comments are parsed into HTML Library documentation
///: Generate library documents for a following item (enclosing item: //!)
Exercise:
1. Write a comment that is one line explaining why you want to learn rust
// I want to learn rust because it has an awesome community!
2. Write a comment that is a short paragraph explaining your favorite recent
tv show
/* My recent favorite tv show is Breaking Bad. I have never
seen it before and it keeps me on the edge of my seat! */
*/
fn main() {
println!("hello, world!");
}
-
17Hello World Example in Rust
-
18What Are Datatypes in Rust
-
19How To Declare Variables in Rust - Strings Integers and Booleans in Rust
-
20Printing Variables as Arguments in Rust
-
21Exercise - Write Variables in Rust
-
22Solution - Write Variables in Rust
/*
Data Types:
A data type, in programming, is a classification that specifies which type of value a variable has and what type of mathematical,
relational or logical operations can be applied to it without causing an error.
Variables:
Variables are used to store information to be referenced and manipulated in a computer program.
Rust is a statically typed language. Every value in rust is of a certain data type.
The compiler automatically infers the data type of a variable based on the value assigned to it
The Type System embodies all the different types of values the language supports.
The type system verifies the supported values, before they are stored or manipulated
by the program. This process just helps to ensure that the code runs as expected
*/
// How do we declare variables in Rust?
// use the let keyword to declare variables in Rust
fn main() {
let financial_management = "Bank Of America"; // string type
let credit_score = "800"; //integer type (are whole numbers no decimals)
// float types take decimals
let account_active = true; // boolean type
println!("My current investor portfolio is managed by: {}", financial_management);
println!("My credit score is: {}", credit_score);
println!("Account Active: {}", account_active);
let switch = false;
let volume = 10;
println!("Launch Mode is set to: {}", switch);
println!("Current Fuel Level is: {}", volume);
}
/*
Exercise: Create two variables in the main function called switch and volume. Assign one of the variables to false and the
other variable the value of 10 and print the results using the print macro twice.
Add strings to provide logical context to the printed results of your choosing
*/
-
23What Are Macros in Rust
-
24What Is The Print Line Println macro in Rust
-
25Print line Println Exericse in Rust
/*
Printing is handled by a series of macros (
Macros simply allows you to invent your own syntax and write code that writes more code.
This is called metaprogramming, which allows for syntactic sugars
that make your code shorter and make it easier to use your libraries.
You could even create your own DSL (Domain-Specific Language) within rust.
A macro is defined with the pre-processor directive.
Macros are pre-processed which means that all the macros would be processed before your program compiles.
However, functions are not preprocessed but compiled.
) defined in std::fmt some of which include:
format!: write formatted text to String
print!: same as format! but the text is printed to the console (io::stdout).
println!: same as print! but a newline is appended.
eprint!: same as print! but the text is printed to the standard error (io::stderr).
eprintln!: same as eprint! but a newline is appended.
*/
fn main() {
// in general, {} will be automatically replaced with any arguments
// and stringified
println!("{} years old", 36);
// named arguments also work
println!("{user1}{action}{user2}",
user1="Mary Lewis",
user2="Jon Wick",
action=" karate kicked ");
// Exercise: Within the function main add a println macro which takes two arguments,
//x and y and stringifies them where x equals "hello " and
// y equals "my friend".
println!("{x}, {y}",
x="hello",
y="my friend")
}
-
26What Are Integers in Rust
-
27Integer Range and Integer Overflow in Rust
-
28Integer Exercise Example in Rust
-
29Integer Solution Example in Rust
/*
Integers In Rust
Integers in Rust are numbers without decimals or number that are not fractionalized
Simply put, integers are data types that represent whole numbers.
Within the umbrella of integers you have signed and unsigned version that you can specify
Signed integers store both negative and postivie values
Unsigned integers may only store positive values
In addition, the size of an integer can be set to arch.
Setting an integer to arch derives the size of the integer to the architecture of the machine
IE if you set it to 64bits then x64 machine
*/
// Examples
fn main() {
let total = 4; // i32 by default
let height:u32 = 41;
let deduction:i32 = 2-200;
println!("the total is {}",total);
println!("the height is {} and the deduction is {}",height,deduction);
// Solution
let time:u16 = 65535;
// 0 to 255 only allowed for u8
let overtime_1:u16 = 65536; //overflow value is 0
let overtime_2:u16 = 65537; //overflow value is 1
println!("time {} ",time);
println!("overflow value 1 is {}",overtime_1);
println!("overflow value 2 {}",overtime_2);
}
/*
The Integer Range
Signed integers can store numbers from -2^(n-1) to 2^(n-1) -1,
where n is the number of bits of the variant.
For example, i16 can store numbers from -(2^15) to 2^15 -1 − here we replaced n with 16.
Unsigned integers can store numbers from 0 to (2^n)-1.
For example, u16 can store numbers from 0 to (2^16)-1, which is equal to 0 to 65535.
The Integer Overflow
An integer overflow occurs when the value assigned to an integer variable exceeds
the Rust defined range for the data type and starts at 0. Let us understand this with an example −
Exercise:
1. In the main function create an unsigned variable of 16 bits to the max total of the range formula
applied to 16 bits.
2. Create two more variables, overtime_1 and overtime_2 where overtime_1 has an overflow value of 0
and overtime_2 has an overflow value of 1.
3. Print your results and check your console for errors. **Important hint: the console
solution should display warning errors since your code should experience overflow.
Good luck!
*/
-
30What Are Variables in Rust
-
31Exercise - What Are Variables in Rust
/*
The Variable Rule Book in Rust
When it comes to Rust there are different ways to name a variable
1. You can name variables with letters, digits, and the underscore character.
2. Variables must begin with either an underscore or an letter
3. Since Rust is case sensitive, upperscore and lowerscore variables are distinct
Data types do not have to be statically declared and are optional.
The data type is applied from the value assigned to the variable.
Immutability
Variables are immutable by default −
read only in Rust. This means that the value of a variable cannot change by default
once it is assigned.
We can apply the mut keyword in order to make the variable mutable.
*/
fn main() {
let mut x = -3;
x = 2;
println!("{}",x);
// Solution
let mut y = 12;
y = 15;
println!("{}",y);
}
/*
// Exercise
1. Create a mutable numerical variable y of the value initialized to 12
2. Change the value to 15 and print the result in the main function
*/
-
32What is Const in Rust - Constants
/*
Constants in Rust
Constants ensures that values in variables cannot be changed.
The keyword for constants is const. Constants must be explicitly stated
with the const keyword.
Naming Convention for Constants:
All characters in a constant variable should be in uppercase for proper
convention.
*/
// overshadowing variables work for variables and will override the variable
fn main() {
let x = 5;
let x = 6;
println!("x changed from 5 to {}", x);
// will not work with constant
const X = 5;
const X = 6;
println!("X changed from 5 to {}", X);
}
-
33What Are String Literals str in Rust
-
34What is The String Object in Rust - new() and len()
-
35What is The String Object in Rust - from() and len()
/*
Strings: String Literal
String literals are a set of characters, which are hardcoded into a variable.
let user="The Incredible Hulk". String literals are found in module std::str.
String literals can also be called string slices.
The String data type in Rust can be applied as such:
String Literal (&str)
String Object (String)
*/
// Example:
fn main() {
let bank:&str="Citi Bank";
let crypto:&str = "Bitcoin";
println!("Bank is: {}, Crypto: {}",bank,crypto);
// String literal static example
let bank2:&'static str="Sky";
let crypto2:&'static str = "Ether";
println!("Bank is: {}, Crypto: {}",bank2,crypto2);
}
/*
String literals are static by default. This ensures string literals are valid for the duration
of the program. You can explicitly declare them as static as well
*/
-
36String Object Methods in Rust
-
37Exercise - Modifying String Literals in Rust
-
38Solution - Modifying String Literals in Rust
/*
What is The String Object
The String object type is derived from the Standard Library.
While the string literal is part of the core language, the string object type is not a part of the core language.
String is in a growing collection and is mutable and UTF-8 encoded type.
The String object type can be used to represent string values that are provided at runtime.
String object is allocated in the heap.
*/
// Example to create a string Object new for empty and we can use from to input
fn main(){
let nothing_within = String::new();
println!("length of this string is {}",nothing_within.len());
let great_movie = String::from("The Big Lebowski");
println!("length is {}",great_movie.len());
// push method
let mut greeting = String::from("tom says ");
greeting.push_str("hello");
println!("{}",greeting);
// Convert a string literal to a string object
let random_string = "Please make me an onbject!".to_string();
println!("{}",random_string);
// Solution
let mut password = "pokemon,".to_string();
password.push_str(" gotta catch them all");
println!("{}",password);
}
/*
STRING OBJECT METHODS:
1 new() pub const fn new() → String Creates a new empty String.
2 to_string() fn to_string(&self) → String Converts the given value to a String.
3 replace() pub fn replace<'a, P>(&'a self, from: P, to: &str) → String Replaces all matches of a pattern with another string.
4 as_str() pub fn as_str(&self) → &str Extracts a string slice containing the entire string.
5 push() pub fn push(&mut self, ch: char) Appends the given char to the end of this String.
6 push_str() pub fn push_str(&mut self, string: &str) Appends a given string slice onto the end of this String.
7 len() pub fn len(&self) → usize Returns the length of this String, in bytes.
8 trim() pub fn trim(&self) → &str Returns a string slice with leading and trailing whitespace removed.
9 split_whitespace() pub fn split_whitespace(&self) → SplitWhitespace Splits a string slice by whitespace and returns an iterator.
10 split() pub fn split<'a, P>(&'a self, pat: P) → Split<'a, P> , where P is pattern can be &str, char, or a closure that determines the split.
Returns an iterator over substrings of this string slice, separated by characters matched by a pattern.
11 chars() pub fn chars(&self) → Chars Returns an iterator over the chars of a string slice.
*/
// *********** ************** *************
/*
Exercise: Manipulating String Objects in Rust
1. In the main function, Create a string literal named password and assign it the value of "pokemon,"
2. Using the String Object push method, modify the password so that it includes " gotta catch them all"
3. Print the result and share your solution on the discord in the Rust channel!
*/
-
39What Are Operators in Rust
/*
What are Operators in Rust
An operator is a character or characters that determine the action that is to be performed or considered.
The data on which operators are actioned are called operands. Consider the following expression −
a + b = c
Here, the values a, b, and c are operands, while + and = are operators.
The major operators to consider in the Rust are the following:
Arithmetic
Bitwise
Comparison
Logical
Bitwise
Conditional
*/
-
40Arithmetic Operators in Rust
/*
Arithmetic Operators
x = 12
y = 2
Show Examples
Sr.No Operator Description Example
1 +(Addition) returns the sum of the operands x + y = 14
2 -(Subtraction) returns the difference of the values x - y = 10
3 * (Multiplication) returns the product of the values x * y = 24
4 / (Division) performs division operation and returns the quotient x / y = 6
5 % (Modulus) performs division operation and returns the remainder x % y = 0
*/
-
41Relational Operators
/*
Relational Operators
Relational Operators check or define the relationship equavalency
between two elements. Relational operators are used to compare two or more values.
Relational operators return a Boolean value − true or false.
x = 5
y = 2
Show Examples
Operator Description Example
1 > Greater than (x > y) is true
2 < Lesser than (x < y) is false
3 >= Greater than or equal to (x >= y) is true
4 <= Lesser than or equal to (x <= y) is false
5 == Equality (x == y) is false
6 != Not equal (x != y) is true
*/
-
42Logical Operators in Rust
/*
Logical Operators
Logical Operators are used to combine and check two or more conditions.
Logical operators return a Boolean value.
Show Examples
x = 1
y = 2
Sr.No Operator Description Example
1) && (And) The operator returns true as long as
all the expressions specified return true
(x > 0 && y > 3) false
2) ||(OR) The operator returns true if at least one of the expressions specified
return true (x > 0 || y > 3) true
3) ! (NOT) The operator returns the inverse of the expression’s result. For E.g.: !(>5)
returns false !(x < 4 ) false
*/
-
43Decision Making Statements in Rust
-
44Rlse If statements and nested If Statements in Rust
-
45Match Statements in Rust
-
46Exercise- Decision Making Structures in Rust
-
47Exercise Solution - Decision Making Structures in Rust
/*
Decision Making Structures in Rust
Decision making structures check statement evaluations and make various outputted decisions programatically based
on the conditions of the statement - whether they may be be true or alternatives if they are false etc
if statement
An if statement consists of a true or fase expression followed by one or more statements.
2
if...else statement
An if else statement in programming is a conditional statement that runs a different
set of statements depending on whether an expression is true or false - Boolean.
3
else...if and nested ifstatement
You can nest one if or else if statement inside another if or else if statement(s) and so on and so forth.
4
match statement
A match statement, similar to the Switch statement in C, allows a variable to be tested against a list of values.
*/
fn main() {
// if statement example:
let num:i8 = 2;
if num > 1 {
println!("number is greater than 1") ;
}
// if else statement example:
let user = "todd";
if user.len() == 4 {
println!("Pass");
} else {
println!("Fail");
}
// else if - nested ladders
let password = "su".to_string();
let pass_num = password.len();
if pass_num > 3 {
println!("thank you for providing a password");
} else if pass_num < 3 {
println!("Your password is too short. Please choose a longer password");
}
let microbiome = "xc12";
let body_part = match microbiome {
"xc12" => {println!("Found match for xc12"); "Tummy Biome"},
"mpt1" => "Eye Biome",
"tttw56" => "finger biome",
_ => "Unknown"
};
println!("The biome match is {}",body_part);
// Exercise Solution
const x: i32 = 3;
const y: i32 = 4;
if x < y && x > 6 {
println!("fail");
} else if x < y || x > 6 {
println!("success");
} else { println!("please try again");
}
}
/*
Exercise: Decision Making Structures in Rust
1. Write two signed 32 bit constants x and y and assign x the value 3 and y the value 4
2. Check to see whether or not the x is less than y and x is greater than 6
3. If the check passes print into the console the following string: "fail"
4. If the check provides a false boolean conduct the following tests:
check if x is less than y or x is greater than 6
If the second test passes print the following string into the console: "success"
Is the second test fails print the following string into the console: "please try again"
*/
-
48What Are Loops in Rust
-
49What Is The For loop in Rust
-
50While Loop in Rust
-
51The Loop Keyword in Rust
-
52Exericse - How To Loop in Rust
-
53Solution - How To Loop in Rust
/*
If you want to repeat a block of code multiple times, which there can be many instances in your program to do so
such as basic calculations for example, you can use loops.
In general, programming instructions happen sequentially:
This means that the first statement in a function would be executed first followed by the enxt and so on
and so forth.
Languages in programming generally
allow us to manipulate the execution paths and customize them more for preference
Rust has 3 different main type of core loops for executing blocks of code
1. while
2. loop
3. for
*/
fn main(){
// for loop example - we call this a definite loop because we run it until
for a in 1..20{ // 20 is not inclusive
if a==2 {
// The continue statement skips the subsequent statements
// in the current iteration and takes the control back to the beginning of the loop
continue;
}
println!("a is {}",a);
}
// an indefinite loop is used when the number of iterations in a loop is indeterminate or unknown
let mut b = 0;
while b < 5{
b = b + 1;
println!("loop b value is {}",b);
}
// also indefinite example
//while true
let mut c = 0;
loop {
c-=1;
println!("c={}",c);
if c==-10 {
// breaks ends the loop and moves control to the next command outside the loop.
break;
}
}
// Exercise Solution
let mut count: u32 = 0;
println!("Let's count until infinity!");
// Infinite loop
loop {
count += 1;
if count == 3 {
println!("Welcome to miami!");
// Skip the rest of this iteration
continue;
}
println!("{}", count);
if count == 5 {
println!("Time to call it a dat!");
// Exit this loop
break;
}
}
}
/*
Exericse: How To Loop in Rust
1. Create a unsigned mutable variable called count of 32 bits
2. Write an infinite loop that increments counts +1 and stores the value in count and has the following conditions:
3. If count is equal to 3 then print the string literal "welcome to miami!" in the console
4. If the count equals 5 then print the string literal "Time to call it a day!" and then exit the loop.
*/
-
54What Is A Function In Rust
-
55What Is A Function In Rust II
-
56Exercise - What Are Functions in Rust
-
57Solution - What Are Functions in Rust
Intermediate to Advanced Videos in Rust
-
58What Are Tuples in Rust
-
59Exercise - Destructing Tuples with Rust
-
60Solution - Destructing Tuples with Rust
/*
** Tuples in Rust **
Tuples are compound data types. A scalar type, or the variables
we've seen so far, can store only one type of data.
For example, an u32 variable will only store a single integer value.
Compound types can store multiple values at the same time of different types.
Tuples have a fixed length - once declared they cannot grow or shrink in size.
The tuple index starts from 0.
*/
// tuple example
fn main() {
let tuple:(i8,f32,i32) = (2, 2.333, 22);
println!("{:?}",tuple);
println!("first value is :{:?}",tuple.0);
// exercise solution
let user2:(i32,bool,&str) = (30,true,"Jack");
user_data(user2);
}
// exercise solution
fn user_data(x:(i32,bool,&str)){
let (age,active,name) = x; //assigns a tuple to distinct variables
println!("age: {}, active: {}, name:
{}",age,active,name);
}
/*
Destructing Tuples in Rust
1. Create a function user_data which takes the tuple x as a parameter containing a
signed integer 32 bits, a boolean, and a string literal (hint: use the &str keyword to point
the reference)
2. In the function assign a tuple to distinct variables by naming the integer: age,
boolean: active, and string literal: name. BIG HINT: let (integer, bool, and string) = x
3. Write instructions in the function to print the age, active status and name
4. In the main function, create a new tuple, user2 and set the user data so that the user is
30 years old, active status is true, and his name is Jack
5. Invoke the user_data passing in user2 as the argument and check the console for your result
Good luck!
*/
-
61What Are Arrays in Rust
-
62Exercise - Loop Through And Modify an Array in Rust
-
63Solution - Loop Through And Modify an Array in Rust
/*
** What Are Arrays in Rust **
An array is a collection of objects of the same type T,
stored in contiguous memory. Arrays are created using brackets [],
and their length, which is known at compile time, is part of their type signature [T; length].
Defining Arrays:
An array consists of sequential memory blocks.
Arrays are static. Arrays cannot be resized once initialized
Each memory block represents an array element.
Array elements are identified by the index
Array element values can be updated or modified but cannot be deleted.
*/
// Array Example
fn main(){
//let arr:[&str;4] = ["kramer","george","elaine","jerry"];
let mut arr = ["kramer","george","elaine","jerry"];
// arrays can also be mutable
arr[2] ="elaine benis";
println!("the seinfeld cast consists of {:?}",arr);
println!("there are a total of {} main characters",arr.len());
// the iter function fetches all the values in an array
for val in arr.iter(){
println!("value is :{}",val);
}
// exercise solution
let mut arr_exercise:[i32;6] = [12,2,3,2,4,5];
for i in 0..6 {
if arr_exercise[i] == 2 {
arr_exercise[i] = 0;
}
println!("index is: {} & value is : {}",i,arr_exercise[i]);
}
}
/*
Loop and mutate an array in Rust
1. Create an array with the following integer values: 12,2,3,2,4,5
2. Write a for loop with can loop through the array and replace all the integer values of 2
with 0. Print the amended results tagged along with the index value of each integer
Good luck and have fun!
*/
-
64The Stack vs The Heap in Rust
/*
** Ownership in Rust **
The Stack vs the Heap
stack:
_ i = 23
_ bool= true
_
_
heap:
---- --- struct - - --
--- - --
Each method has its own stack designed for primitives (when the method is done you can clean the stack out)
Pointer on the stack will point to an object
Structs could be on the heap (not as efficient and fast and have to find space to allocate it)
Rust does not use a garbage collector,
but rather achieves these properties through a sophisticated,
but complex, type system. Doing so makes Rust very efficient, but makes Rust relatively hard to learn and use.
**********
The stack is very fast, and is where memory is allocated in Rust by default.
But the allocation is local to a function call, and is limited in size.
The heap, on the other hand, is slower, and is explicitly allocated by your program.
But it’s effectively unlimited in size, and is globally accessible.
Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary order,
is quite different from the heap data structure.
when a function gets called, some memory gets allocated for all of its local
variables and some other information. This is called a ‘stack frame’
So if the stack is faster and easier to manage, why do we need the heap?
A big reason is that Stack-allocation alone means you only have 'Last In First Out (LIFO)'
semantics for reclaiming storage. Heap-allocation is strictly more general,
allowing storage to be taken from and returned to the pool in arbitrary order, but at a complexity cost.
Generally, you should prefer stack allocation, and so, Rust stack-allocates by default.
The LIFO model of the stack is simpler, at a fundamental level. This has two big impacts:
runtime efficiency and semantic impact.
*/
-
65Ownership in Rust
/*
** Ownership in Rust **
The Stack vs the Heap
Recall ---
stack:
_ i = 23
_ bool= true
_
_
heap:
---- --- struct - - --
--- - --
Variables of a value have an owner in Rust.
All the data this is stored in Rust has an owner associated to it.
let time = 20 - time is the owner of the value 20
Data only has one owner at a time.
Multiple variables cannot point to the same memory location
Variables always point to different memory locations
That being said, you can transfer ownership in Rust:
Assigning one variable's value to another variable.
Inputting value to a function.
Outputting value from a function.
A vector is a data structure that contains zero-or-more items of the same type.
The items have an order, and you can access the items by index (0, 1, ...).
You can add and remove items. The items themselves are stored in a contiguous heap-allocated area.
*/
fn main(){
let vector1 = vec![1,2,3];
// vector v owns the object in heap
//only a single variable owns the heap memory at any given time
let vector2 = vector1;
//two pointers to the same content is not allowed in rust
//Rust will check for memory access which is a key selling point for using the language
println!("{:?}",vector1);
}
-
66Borrowing In Rust - The & Symbol in Rust
-
67Exericse - Borrowing in Rust
-
68Solution - Borrowing in Rust
/*
Borrowing In Rust
It can be quite a hastle transferring ownership of a variable to another function
and then returning ownership. Through temporarily transferring ownership of a value,
Rust supports borrowing ownership in which the ownership is then returned to the original owner.
Functions can transfer their control of a value to another function temporarily and that is
what we call borrowing in Rust. You can pass a reference to the variable with (& var_name)
as opposed to passing the variable itself. The ownership of the variable/ value is transferred
to the original owner of the variable.
*/
fn main(){
let vector = vec![1,2,3];
//display(vector);
display(&vector);
println!("{}",vector[1]); // this will not work
// Exercise Solution
let mut car:String = String::from("Ferrari");
display2(&mut car);
//pass a mutable reference of name
println!("The car has been updated to: {}",car);
}
//fn display(x:Vec<i32>){
fn display(x:&Vec<i32>){
println!("{:?}",x);
}
fn display2(_car:&mut String){
println!("_car value is :{}",_car);
_car.push_str(" F8 Tributo");
//Modify the actual string,name
}
/*
Borrowing and References Exercise in Rust:
Create a function called display2 which takes a string object as a parameter and pushes onto
the string an "F8 Tributo" which is an awesome type of Ferrari!
Create variable car which is a string object with the default "Ferrari". Call display2 passing in the car
variable as the argument and print the modified version of the variable car.
Good luck!
*/
-
69How To Slice in Rust
-
70Exercise - How To Slice in Rust
-
71Solution - How To Slice in Rust
/*
Slices in Rust
Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.
A slice is a kind of reference, so it does not have ownership.
Slices essentially point to data.
They are passed by reference to functions ie borrowing. You can use them to fetch portions of data and customize
what you want to slice.
*/
// Slice Example
fn main() {
let game = "Mario Brothers".to_string();
println!("length of the game is {}",game.len());
let slice = &game[0..5];
println!("{}",slice);
// Exercise Solutio n
let mut nums = [1,2,3,4,5];
slice_and_dice(&mut nums[1..3]);
// passes references
println!("{:?}",nums);
}
fn slice_and_dice(slice:&mut [i32]) {
println!("length of slice is {:?}",slice.len());
println!("{:?}",slice);
slice[0] = 200;
}
/*
1. Create an array with the values 1 through 5 called nums.
2. Print the values of nums.
3. Write a function called slice_and_dice which takes an array as a parameter and prints the length of the
array. It should also print the updated value of the array. The function should also replace the first index value
in the array to 200.
4. Call the slice and dice function in the main function and slice out the values 2 and 3 from the array.
There are a few little tricks here so be vigilent and good luck!
*/
-
72What Are Structs in Rust
-
73Exercise - Write Methods and Structs in Rust
-
74Solution - Write Methods and Structs in Rust
/*
Wbat are Structs in Rust
Structs are similar to tuples, discussed in “The Tuple Type” section,
in that both hold multiple related values. Like tuples, the pieces of a struct can be different types.
Unlike with tuples, in a struct you’ll name each piece of data so it’s clear what the values mean.
Adding these names means that structs are more flexible than tuples:
you don’t have to rely on the order of the data to specify or access the values of an instance.
Structs use key value pairs to define data.
Rust allows to combine data items of different types,
including other structures.
*****
Methods are functions which belong in the scope within a structure.
You declare methods with the impl keyword outside of the structure block.
Important to note that the parameter of a method will be always self,
which represents the calling instance of the structure.
Example:
struct The_struct {
impl The_struct {
fn method_name(&self) {
}
}
}
*/
// Struct Example
struct House {
door:String,
garden:String,
property_value:u32
}
// Exercise Solution
struct Triangle {
base:u32,
height:u32
}
impl Triangle {
fn find_area(&self) -> u32 {
return self.base * self.height / 2;
}
}
fn main() {
let home1 = House {
door:String::from("Blue"),
garden:String::from("Beautiful"),
property_value:1000000
};
println!("door is: {}, garden is: {}, property value is: {}",
home1.door, home1.garden, home1.property_value);
let new_triangle = Triangle {
base:10,
height:30
};
println!("the area of the triangle is: {}", new_triangle.find_area());
}
/*
Build A Triangle Calculator in Rust with Structs
1. Write a Triangle struct that takes the key pair values of base and height as unsigned integers
2. write a method for the Triangle which can calculate the area of the triangle (remember the triangle area
formula is base * height / 2)
3. Create a new triangle struct and set the base to 10 and the height to 30
4. Print the method calculation for the area of the new triange.
Good Geometric luck!
*/
-
75What Are Enums in Rust
-
76Exercise - Matching Enums in Rust
-
77Solution - Matching Enums in Rust
/*
What Are Enums in Rust
An enum type is a special data type that enables for a variable to be a set of predefined constants.
The variable must be equal to one of the values that have been predefined for it.
Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
*/
// Example Enum
// the derive attribute makes the enum printable
#[derive(Debug)]
enum TemperatureGrade {
Hot,Cold,Medium
}
#[derive(Debug)]
struct City {
name:String,
temperature:TemperatureGrade
}
enum Shoes {
Nike,
Loafer,
Vans
}
fn print_shoes(shoe:Shoes) {
match shoe {
Shoes::Nike => {
println!("Great for running!");
},
Shoes::Loafer => {
println!("Great for loafing around!");
},
Shoes::Vans => {
println!("Great for skateboarding!");
}
}
}
fn main() {
let c1 = City {
name:String::from("Alaska"),
temperature:TemperatureGrade::Cold
};
let c2 = City {
name:String::from("Miami"),
temperature:TemperatureGrade::Hot
};
println!("{:?}",c1);
println!("{:?}",c2);
// Exercise Solution
print_shoes(Shoes::Nike);
print_shoes(Shoes::Loafer);
print_shoes(Shoes::Vans);
}
/*
Extra hint:
Match keyword -
Match a single value
1 => println!("One!"),
Matching Enums In Rust Exercise
1. Write an Enum for three different types of shoes: loafer, nike, and vans
2. Using the match keyword, write a function that takes the enum as a value and can
match each shoe with the following printed string values:
nike: "Great for running", loafer: "Great for loafing around", vans: "Great for skateboarding"
3. call the function and print each string match by passing in each enum value as an argument
and printing the matched result
*/
-
78What Are Modules in Rust
-
79Exercise - Nested Modules in Rust
-
80Solution - Nested Modules in Rust
/*
What Are Modules in Rust
Rust provides a powerful module system that can be used to hierarchically split code in logical units (modules),
and manage visibility (public/private) between them. A module is a collection of items:
functions, structs, traits, impl blocks, and even other modules.
Multiple modules are compiled into a unit called crate. The Cargo tool is used to manage crates in Rust.
**************
crate
Compiling unit in Rust compiled to binary or library.
2
cargo
The official Rust package management tool for crates.
3
module
a collection of items: functions, structs, traits, impl blocks, and even other modules.
4
crates.io
The official Rust package registry.
*/
// The use keyword helps to import a public module.
// functions are defaulted to private
// Module Example in Rust
pub mod songs {
pub fn play(name:String) {
println!("track selection: {}", name);
}
}
use songs::play;
// Exercise Solution
pub mod tracks {
pub mod rock {
pub mod indie {
pub fn select(name:String) {
println!("Track selection is: {}", name);
}
}
}
}
use tracks::rock::indie::select;
// imported a public module
fn main() {
// play("Kissed By A Rose".to_string());
select("Serenade".to_string());
select("French Baguette".to_string());
select("Pineapple Blues".to_string());
}
/*
Exercise - Nested Modules in Rust
1. create a module named tracks that contains a module named rock that contains
another module indie which contains a function called select which takes a String object as a paramenter and
prints the string
2. Import select and in the main function call select three times printing the following song titles: "Serenade", "French Baguette"
and "Pineapple Blues"
*/
-
81What are HashMaps in Rust
-
82Exercise - Build A Hash Table with HashMap in Ruat
-
83Solution - Build A Hash Table with HashMap in Rust
/*
What Are HashMaps in Rust
Rust's standard collection library has implementation of some of the most common
data structures for general purposes. We've seen vectors previously, now let's take a look at HashMaps!
the type HashMap<K, V> stores a mapping of keys of type K to values of type V.
It does this via a hashing function, which determines how it places these keys and values into memory.
Many different programming languages support this kind of data structure,
but often use a different name, such as hash, map, object, hash table, or associative array, just to name a few.
Hash maps are useful for when you want to look up data not by an index, as you can with vectors,
but by using a key that can be of any type. For example, in a game, you could keep track of each team’s
score in a hash map where each key is a team’s name and the values are each team’s score. Given a team name,
you can retrieve its score.
No two entries in a map can have the same key. In short, a map is a lookup table.
1 insert()
pub fn insert(&mut self, k: K, v: V) -> Option
Inserts a key/value pair
2 len()
pub fn len(&self) -> usize
finds and returns how many elements are in the map
3 get()
pub fn get<Q: ?Sized>(&lself, k: &Q) -> Option<&V> where K:Borrow Q:Hash+ Eq
returns a ref to the value of a key
4 iter()
pub fn iter(&self) -> Iter<K, V>
Iteration through all key-value pairs
5 contains_key
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
Returns bool whehter a value is true for a specified key
6 remove()
pub fn remove_entry<Q: ?Sized>(&mut self, k: &Q) -> Option<(K, V)>
Removes a key from the map
*/
// HashMap Example
use std::collections::HashMap;
fn main() {
let mut accountInfo = HashMap::new();
accountInfo.insert("Johnny","Overdraft!");
accountInfo.insert("Sally","Good Standing!");
//accountInfo.insert("Superman","Insufficient funds!");
println!("the size of the accountInfo map is: {}", accountInfo.len());
let mut barDrinks = HashMap::new();
barDrinks.insert("vodka", true);
barDrinks.insert("beer", false);
barDrinks.insert("whiskey", true,);
println!("the size of the barDrinks map before we remove one k/v is: {}", barDrinks.len());
barDrinks.remove(&"whiskey");
println!("the size of the barDrinks map after we remove one k/v is: {}", barDrinks.len());
}
/*
Exercise - Build A hash table with Hashmap in Rust
1. Create a new HashMap instance variable barDrinks and using the insert method
add three new key pair values to your table: vodka, beer, and whiskey as keys and the values
should be set up so that vodka and whiskey indicate that the bar has some left while beer has all run out.
2. Remove whiskey from the local table.
Good luck and keep those patrons drinking and happy!
*/