Welcome to Rust! In this series, we'll cover the basics of Rust programming, starting from installation and setup to writing and running your first program. We'll also cover key data types, variables, and basic operations with examples and edge cases.


1. Installing Rust

🛠️ Install Rust using rustup

rustup is the recommended way to install Rust as it manages updates and toolchains easily.

➡️ Steps to install:

  1. Open your terminal.
  2. Run the following command:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  1. Follow the on-screen instructions.
    • It will install:
      • rustc – The Rust compiler
      • cargo – The Rust package manager
      • rustup – The version manager

Verify Installation

After installation, restart your terminal and run:

rustc --version
cargo --version

Example output:

rustc 1.76.0 (f9e8851be 2025-03-01)
cargo 1.76.0 (f9e8851be 2025-03-01)

🚀 2. Setting Up Your First Rust Project

➡️ Create a new Rust project

Use cargo to create a new project:

cargo new hello-rust

This creates a directory hello-rust with the following structure:

hello-rust
├── Cargo.toml   // Project configuration file
└── src
    └── main.rs  // Main code file

📝 3. Writing Your First Program

Open src/main.rs and write the following:

fn main() {
    println!("Hello, Rust!");
}

➡️ Run the program

Navigate to the project directory and run:

cargo run

✅ Output:

Hello, Rust!

🔢 4. Numbers in Rust

Rust has strict type-checking for numeric types:

➡️ Signed Integers (i8, i16, i32, i64, i128)

  • Signed integers can store negative values.
  • i32 is the default type for integers.

Example:

let x: i32 = -10;
let y: i32 = 20;
println!("Signed Integers: x = {}, y = {}", x, y);

➡️ Unsigned Integers (u8, u16, u32, u64, u128)

  • Unsigned integers store only positive values.

Example:

let x: u32 = 10;
let y: u32 = 20;
println!("Unsigned Integers: x = {}, y = {}", x, y);

➡️ Floating-Point Numbers (f32, f64)

  • f64 is the default type for floats.

Example:

let x: f32 = 10.5;
let y: f32 = 20.5;
println!("Floats: x = {}, y = {}", x, y);

Edge Cases

  1. Integer overflow example:
let x: u8 = 255;
let y = x + 1; // Causes overflow
println!("{}", y);

➡️ Output: thread 'main' panicked at overflow

  1. Floating-point precision loss:
let x: f32 = 0.1 + 0.2;
println!("{}", x); // Output: 0.30000004

🔣 5. Booleans in Rust

Rust uses true and false for booleans.

Example:

let is_true: bool = true;
let is_false: bool = false;

if is_true && !is_false {
    println!("Both conditions are satisfied.");
} else {
    println!("Conditions are not satisfied.");
}

Edge Cases:

  1. Boolean used in if expression:
let condition = 1 > 2;
if condition {
    println!("True");
} else {
    println!("False");
}

🏷️ 6. Variables in Rust

  • Variables are immutable by default.
  • Use mut to make them mutable.

Example:

let x = 10; // immutable
let mut y = 20; // mutable

y = 30; // OK since it's mutable
println!("x = {}, y = {}", x, y);

Edge Cases:

  1. Trying to modify an immutable variable:
let x = 10;
x = 20; // Compile-time error
  1. Shadowing example:
let x = 10;
let x = x + 20;
println!("{}", x); // Output: 30

🔡 7. Strings in Rust

Rust has two types of strings:

  1. String – Heap-allocated and growable
  2. &str – String slice (fixed size)

➡️ Example of String:

let greeting: String = String::from("Hello, Rust!");
println!("{}", greeting);

➡️ Example of &str:

let x: &str = "Hello";
let y: &str = "Rust";
println!("{} {}", x, y);

Edge Cases:

  1. String indexing is not allowed:
let s = String::from("hello");
println!("{}", s[0]); // Error: Rust strings are UTF-8
  1. String length:
let s = String::from("hello");
println!("{}", s.len()); // Output: 5
  1. Handling Option when indexing:
let s = String::from("rust");
match s.chars().nth(2) {
    Some(c) => println!("Third character: {}", c),
    None => println!("No character at index"),
}

🪓 8. Match Statement

Example:

let x = 5;

match x {
    1 => println!("One"),
    2 => println!("Two"),
    3..=5 => println!("Three to Five"),
    _ => println!("Other"),
}

Edge Cases:

  1. Missing cases:
let x = 7;
match x {
    1 | 2 => println!("One or Two"),
    _ => println!("Other"),
}

📚 9. Functions in Rust

Example:

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn main() {
    let result = add(5, 10);
    println!("Sum = {}", result);
}

Edge Cases:

  1. Mismatched return type:
fn add(x: i32, y: i32) -> i32 {
    x + y;
} // Error due to missing return statement without `;`

🏆 10. Full Example

fn main() {
    let x: i32 = 5;
    let y: i32 = 10;
    println!("Sum of {} and {} is {}", x, y, add(x, y));
}

fn add(a: i32, b: i32) -> i32 {
    a + b
}

➡️ Output:

Sum of 5 and 10 is 15

➡️ Clone the repo:

git clone https://github.com/ichiragkumar/rust-basics.git

➡️ Navigate to the project:

cd rust-basics

➡️ Run the project:

cargo run

➡️ Edit and Play Around:

Open src/main.rs in your editor (like VSCode) and start modifying it:

✅ Add new functions

✅ Test edge cases

✅ Break things to see how Rust handles it


🚀 Follow and Explore!

👉 Follow Chiragkumar on GitHub and X:

  • GitHub – Star the repo and check out other cool projects! 🌟
  • X (Twitter) – Stay updated with Chiragkumar's coding journey! 🧑‍💻