0% found this document useful (0 votes)
69 views32 pages

Rust 1: Curl - Proto ' HTTPS' - Tlsv1.2 - SSF HTTPS://SH - Rustup.Rs - SH Rustc - Version Cargo - Version

This document provides an overview of the Rust programming language. It discusses Rust's package manager Cargo, variables and data types, functions, conditional statements like if/else, and loops like for and while. It also covers topics like arrays, tuples, operators, and formatting strings for output. The document is an introduction to many core concepts in Rust.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views32 pages

Rust 1: Curl - Proto ' HTTPS' - Tlsv1.2 - SSF HTTPS://SH - Rustup.Rs - SH Rustc - Version Cargo - Version

This document provides an overview of the Rust programming language. It discusses Rust's package manager Cargo, variables and data types, functions, conditional statements like if/else, and loops like for and while. It also covers topics like arrays, tuples, operators, and formatting strings for output. The document is an introduction to many core concepts in Rust.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 32

🦀

RUST
https://www.linkedin.com/learning/rust-essential-training/anatomy-of-a-rust-program?
autoSkip=true&autoplay=true&dApp=112132386&leis=LAA&resume=false&u=67551194

Install Rust using curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

rustc —version

cargo —version

rustc main.rs

cargo new hello_world .→

Cargo is a package manager for rust.

Cargo.toml (toms obvious minimal language ) contains project configurations.


Along with that by default cargo initialize git & .gitignore is created.

Package (Project name, version, author, edition)

RUST 1
Dependencies
To include external libraries for dependency

cargo run will compile and build the project


By default cargo build’s project with debug enabled & it also creates additional.

folder target/ & Cargo.lock file

cargo build —release will create a release/ directory with optimizations.

cargo book has more precise details to maintain the project.

Variables
variable in rust starts with let

fn main(){

let x = 10;

println!(”x is {}”, x);

Rust variables are immutable by default.

RUST 2
The variable must be explicitly declared as mute in order to change the value.
fn main(){

let mut x = 10;

println!(”x is {}”, x);

x = 20;

Note: variable cannot be keywords let or mut

Note: As a convention snake case is followed for all the local variables in rust.

Rust is a statically typed language - every variable should be defined at compile time.

Ruts is also a strongly typed language - ( implicit ) dynamically changing data types of
the variables at runtime is not allowed.

Integers :

By default rust use i32 (signed 32 integers).


let x : u8 = 10

fn main(){

let x : u8 = 255;

x = x + 1;

println(” x is {} ”, x);

RUST 3
}

Rust catches these overflow at compile time itself in the latest versions.

Overflow at runtime will lead to panic and asserts the program from running.

Float :
Rust supports f32 & ( f64 as default).
let x = 22.0/7.0

Arithmetic Operations:
Rust support ( + - * / %)

Typecasting :
let x = 10;

let b = 3.0;

let c = a as f64/b;

Note: Be aware of losing data while casting b/w different types.

eg : let x = 300;

let y = x as u8; → y = 44 as it losses data.

BODMAS:

RUST 4
Formatting:
println!(" x is {}", c); → x is 2.33333333335

println!(" x is {:.3}", c); → x is 2.333


println!(" x is {:8.3}", c); → x is 2.333 (padded with 8 spaces)

println!(" x is {:8.3}", c); → x is 000000002.333 (padded with 8 zeros)


Note : println! adds a new line at the end of the line.

print! no \n at the end of the line.


println!(”a is {} b is {} a is {0}”, a, b); value in braces takes the position of the
argument.
println!(” x is {:08b}”, x); → x is 00010011 (prints in binary)

Bitwise :
Rust allows defining binary data.

let x = 0b000010011 . or let x = 0b0001_0011

let x : u8 = 0b000010011 . . or let x = 0b0001_0011u8

NOT → x = !x;

AND → x = x & 0b0000_1111;

OR . → x = x | 0b0000_1111;

XOR → x = x^0b0101_0101;

SHIFT → x = x<<2;

RUST 5
Boolean :
let x = true;

let y = false;

Short-circuiting or Logical AND, OR :


&& ||

Comparison Operator:
== != <= >= > <

Note: Rust doesn't allow comparing data in different data types.

Char data type:


Rust uses 4 bytes to store characters’ data type by default.
let x = ‘a’;

let x = ‘1’;

let x = ’\u{261D}’;

Array :
The array holds multiple values of the same data type in a consecutive memory
location.
fn main(){

let mut array = [’a’, ‘b’, ‘c’];

println!(” first letter {}”, array[0]);

let numbers: [i32; 5];

println!(” first number {}”, numbers[0]); →compile error reading uninitialized array

numbers = [1, 2, 3, 4, 5];

println!(” first number {}”, numbers[0]);

println!(” first number {}”, numbers[5]); → compile time error index our of range
let n = 6;

RUST 6
println!(” first number {}”, numbers[n]); → run time panic

let array_len: usize = numbers.len(); → size of usize depends on platform(4 bytes 32bit)

let garage [[[i32; 100]; 20]; 5]; → 5 floors, 20 rows, 100 cars in each

Initializing an array

Semi Initialised array is not allowed

RUST 7
Initializing an array with variable is not allowed in rust

Tuple:

Tuple holds multiple values of multiple data types in consecutive memory locations.

fn main() {

let mut stuff = (1, 3.14, ‘x’);

let first_item = stuff.0;

stuff.0 += 1;

let (a, b, c) = stuff;

println!(” second item {}”, b);

Functions :
Rust functions doesn't need declarations.

fn main(){

RUST 8
say_hello() ;
}

fn say_hello(){

println!(” Hello ”);

say_number();

fn say_number(number: i32){

println!(”number {}”, number);

let x = 1;

let y = 2;

say_sum(x, y); → since we did not specify the data type of x, y, and say_sum is the first
function it encountered that takes x & y as parameters compiler assumes x & y as u8 .

Note : It's not an implicit dynamic typecast

say_number(x); → will throw a compile time error because compiler previously assumed
that x is u8

say_numer(x as i32);

fn say_sum(a: u8, b: u8){

let sum = a+b;

println!(”Sum {}”, x);

Statement vs Expression:
The statement is an expression without a return value & ends with a semicolon.
An Expression will have a result & does not end with semicolon.

RUST 9
Return :
fn square(x: i8) -> u32 {

x * x

fun Square(n: i8) -> (i8, u32) {

return (x, x * x);

fn main(){

let result = Square(5);

println!(” result {?}”, result); rust doesn't have a format specifier for tuple so we can
use a compiler format specifier ? to print a tuple
}

If the function doesn't return anything by default, the compiler assumes it returns a unit
value.

eg:
fn hello() → (){

RUST 10
Conditional Execution:
fn main () {

let x = 3;

if x == 3 {

println!(” Condition is True”);

Rust if condition expects boolean


fn main () {

let x = 3;

if x { . → compilation error saying expected bool at if condition


println!(” Condition is True”);

if true { → is valid
println!(” Condition is True”);

IF - ELSE, ELSE IF:

RUST 11
RUST 12
IF- ELSE in single line
fn main (){

let condition = true;

let x = if condition {3} else {4};

fn main (){

let condition = true;

let x = if condition {3} else {4.0}; → Compile error if and else have incompatible
types.
}

Loops :
loop → loop is basically infinite loop and need as break statement to exit the loop

RUST 13
We can make loop typically a statement and make it to return a value

while

While does not have the ability to return a value.

RUST 14
for

Under the hood for loop converts the message array into an iterator, iterator has a
method next() this for loop use this next method internally and iterate through the
message array till the end.

if we are using older version of rust than 1.5 then we should use message.iter()

method to iterate through the array.

we can get index of the array by using array.iter().enumerate() this returns a tuple
with index and value

We can have a break inside for loop.

RUST 15
Iterate through loop for a range of values.

RUST 16
Nested Loops :

Modifying values in an nested array.

RUST 17
Variable Scope
In rust, variable bindings are constrained to live within a block of code.
{

let planet = “Earth”;

Rust allows redeclaring / shadowing the same variable name.

fn main() {
let message = [1, 2, 3 ];
println!("{}", message); -> [1, 2, 3]
let message = "hello";
println!("{}", message); -> hello
}

fn main(){
let planet = "earth";
if true{
let planet = "mars";
println!("{}", planet); -> mars
}
println!("{}", planet); -> earth
}

String literal
Rust string data type is called string literal cause it's literally written in the code, the
compiler will hardcode the string into the executable.

When the program runs it gets loaded into the memory, when the program needs to use
the literal value it will access using the reference.

There is one more variant called string type

RUST 18
fn main(){
let message: String = String :: from("Earth"); -> string type
let planet: &str = "Earth"; -> string literal
}

fn main(){
let mut message = String :: from("Earth");
message.push_str("is home");

RUST 19
Ownership
Variables are responsible for freeing their own resources.

Rules

Every value is owned by one and only one variable at a time.

When the owning variable goes out of scope the value is dropped.

Scenario for data on Heap.

fn main(){

let outer_planet: String;


{
let inner_planet: String = String::from("Mercury");
println!("{}", inner_planet);
outer_planet = inner_planet; -> its not a copy but a move
}

RUST 20
println!("{}", outer_planet);
}

fn main(){

let outer_planet: String;


{
let inner_planet: String = String::from("Mercury");
println!("{}", inner_planet);
outer_planet = inner_planet.clone();
}
println!("{}", outer_planet);}
fn main(){

let outer_planet: i32;


{
let mut inner_planet = 1;
outer_planet = inner_planet;
inner_planet += 1;
println!("{}", inner_planet);
}
println!("{}", outer_planet);
}

RUST 21
Scenario if data is in Stack.

fn main(){

let outer_planet: i32;


{
let mut inner_planet = 1;
outer_planet = inner_planet;
inner_planet += 1;
println!("{}", inner_planet);
}
println!("{}", outer_planet);
}

RUST 22
Transferring ownership

fn main(){
let rocket_fuel = 1;
process_fuel(rocket_fuel);
println!("{}", rocket_fuel);
}

fn process_fuel(propellant: i32){
println!("{}", propellant);
}

Now make the variable heap-based

fn main(){
let rocket_fuel: String = String::from("RP-1");
process_fuel(rocket_fuel);
println!("{}", rocket_fuel); -> compilation error value is moved
}

fn process_fuel(propellant: String){
println!("{}", propellant);
}

When a heap-based variable is passed as an argument the ownership is transferred.

Fix for the above compile time issue.

RUST 23
fn main(){
let rocket_fuel: String = String::from("RP-1");
let rocket_fuel = process_fuel(rocket_fuel);
println!("{}", rocket_fuel);
}

fn process_fuel(propellant: String)-> String{


println!("{}", propellant);
propellant
}

fn main(){
let rocket_fuel: String = String::from("RP-1");
let rocket_fuel = process_fuel(rocket_fuel.clone());
println!("{}", rocket_fuel);
}

fn process_fuel(propellant: String){
println!("{}", propellant);
}

Borrowing References

fn main(){
let rocket_fuel: String = String::from("RP-1");
let length = process_fuel(&rocket_fuel); & -> borrow operator (reference)
println!("{} {}", rocket_fuel, length);
}

fn process_fuel(propellant: &String) -> usize{


println!("{}", propellant);
propellant.len()
}

RUST 24
Borrowing mutable reference

fn main(){
let mut rocket_fuel: String = String::from("RP-1");
let length = process_fuel(&mut rocket_fuel);
println!("{} {}", rocket_fuel, length);
}

fn process_fuel(propellant: &mut String) -> usize{


propellant.push_str("is highly flamable");
println!("{}", propellant);
propellant.len()
}

Note : while using a mutable reference, it's not allowed to create another reference in
that scope.

Even though the other references are nonmutable it's not allowed.

This is to prevent data races (every object should have only one owner at any instance).

RUST 25
Dangling reference

fn main(){
let fuel = process_fuel();
}

fn process_fuel() -> &String {


let fuel = String :: from("RP - 1");
&fuel -> compilation error
}

Returning a pointer to a local variable creates a dangling pointer, rust doesn't allow it.

Fix for the above problem instead of creating a dangling pointer pass the owner ship.

fn main(){
let fuel = process_fuel();
println!("{}", fuel)
}

fn process_fuel() -> String {


let fuel = String :: from("RP - 1");
fuel
}

RUST 26
Slices
In order to create references for sub set for an array/strings we use slices.

Slice of String gives str

fn main(){
let messge = String::from(" Message from Earth! ");
let last_word: &str = &messge[14..14+5];
println!("{}", last_word);
}

fn main(){
let messge = String::from(" Message from Earth! ");
let last_word: &str = &messge[14..14+50]; -> compiles but panics at runtime
println!("{}", last_word);
}

fn main(){
let planets:i32 = [1, 2, 3, 4, 5, 6, 7, 8]
let inner_planets: &[i32] = &planets[..4];
println!("{:?}", inner_planets);
}

Slices as function parameters

fn main(){
let message: String = String::from("Message from Earth !");
let first_word: &str = get_first_word(&message);
println!("{}", first_word);
}

fn get_first_word(message: &String) -> &str{

for (index, letter) in message.chars().enumerate(){


if letter == ' '{ // found a space
return &message[..index]; // returning first word

RUST 27
}
}
return &message; //no space found return entire string
}

&String is not equal to &str .

RUST 28
But String can act as str because str itself doesn't own any object its just a slice
(contains pointer and its length but not capacity ), but vice versa is not possible.

Trim Spaces

fn main(){
let message: String = String::from("Message from Earth !");
let no_spaces = trim_spaces(message.clone());
println!("{}", no_spaces);

fn trim_spaces(message: String) -> String {


let mut offset = 0;
let mut no_spaces = String::from("");
for (index, letter) in message.chars().enumerate(){
if letter == ' '{
no_spaces.push_str(&message[offset..index]);
offset = index+1;
}
}
no_spaces
}

Rust Standard Library & Prelude

Ruts come with a standard library std which is not a part of rust language but a
module.

We can import these modules from std using key word use . eg : use std::thread;

Stringis a part of std . but we don't need to import it with std every time we use is
because

it's a part of prelude , prelude only includes the most common modules used.

Any module that is not a part of pelude needs to be imported to be used.

Standard input

use std::io;

RUST 29
fn main() {
let mut buffer = String::new();
println!("Enter message ");
io::stdin().read_line(&mut buffer);
println!("Input is {}", buffer);
}

Std input by default returns string (with a \n at the end), if we want to convert the input
and use it we need to parse it.

use std::io;

fn main() {
let mut buffer = String::new();
println!("Enter number :");
io::stdin().read_line(&mut buffer);
let number: i32 = buffer.trim().parse().unwrap();
println!("Input + 1 is {}", number+1);
}

There is furthermore to cover about stdin and parse

Crate
In rust, the therm crate refers to the collection of rust source code files.

Binary crate is used to compile and create an executable.(typically main)

Library crate that is used by the other programs.

crates.io is the official source for crates from rust community.

In order to use these crates in our program, we need to add them to cargo.toml file.

[dependencies]
rand = "0.8.5"

use rand;

fn main() {

RUST 30
let number = rand::random::<f64>();
println!("Random number is {}", number);
}

rand comes with its own prelude which includes the most common functions in rand.

use rand::prelude::*;

fn main() {
let number = random::<f64>();
println!("Random number is {}", number);

let n = thread_rng().gen_range(1..10);
println!("Thred Random number generator {}", n);

Higher or lower game

use rand;
use std;

fn main(){
let secretVal = rand::thread_rng().gen_range(1..50);
println!("--- START GAME ---");
loop{

let mut count = 0;


let mut buffer = String::new();
while(count < 5){
std::io::stdin().read_line(&mut buffer).expect("Failed to read input");
let guess: i32 = buffer.trim().parse().expect("Failed to parse the guess");
buffer.clear();
if secretVal == guess{
println!("Congrats your guess is correct !");
break;
} else if secretVal > guess{
println!("You gess is small");
} else {
println!("You gess is big");
}
count +=1 ;
}
println!("Enter 1 to continue 0 to quit");
std::io::stdin().read_line(&mut buffer).expect("Failed to read choice");
let choice: i32 = buffer.trim().parse().expect("Failed to parse the choice");
if choice == 0{
break;
}
count = 0;

RUST 31
}
println!("--- GAME END ---");
}

RUST 32

You might also like