Chapter 8: Rust Data Types
Rust Data Types. This is a very important chapter because Rust is statically typed (compiler knows every type at compile time), which gives you safety + speed, but you need to understand what types exist and how they behave.
Rust divides data types into two big groups (just like the official Rust Book chapter 3.2 explains):
- Scalar types → represent a single value (simple building blocks)
- Compound types → group multiple values together into one type
Let’s go deep, slowly, like we’re sitting together with code open, using everyday Hyderabad examples (weather, biryani, traffic 😄), lots of copy-paste code, and clear explanations of ranges, sizes, and why things matter.
1. Scalar Types (Single Values — The Four Main Families)
Rust has four primary scalar types:
A. Integers (Whole Numbers — No Fractions)
Integers come in signed (can be negative) and unsigned (only positive or zero).
Naming:
- i = signed (i for integer, can be negative)
- u = unsigned (u for unsigned, always ≥ 0)
- Number after = bits (8, 16, 32, 64, 128)
- Special: isize / usize = size depends on your computer (64-bit usually → 64 bits)
| Type | Bits | Signed? | Min Value | Max Value | Common Use Example |
|---|---|---|---|---|---|
| i8 | 8 | Yes | -128 | 127 | Small counters, temperatures offset |
| u8 | 8 | No | 0 | 255 | Bytes, RGB colors (0–255) |
| i16 | 16 | Yes | -32,768 | 32,767 | Short IDs |
| u16 | 16 | No | 0 | 65,535 | Unicode code points sometimes |
| i32 | 32 | Yes | -2,147,483,648 | 2,147,483,647 | Default integer — most common |
| u32 | 32 | No | 0 | 4,294,967,295 | Counts, sizes |
| i64 | 64 | Yes | -9 quintillion… | 9 quintillion… | Big timestamps, money in paise |
| u64 | 64 | No | 0 | 18 quintillion… | File sizes, nano-seconds |
| i128 | 128 | Yes | huge negative | huge positive | Cryptography, very big math |
| u128 | 128 | No | 0 | enormous | Rare, crypto hashes |
| isize | arch | Yes | depends (usually i64) | depends | Pointer/index sizes |
| usize | arch | No | 0 | depends | Array lengths, memory addresses |
Example:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
fn main() { let temperature: i32 = 32; // default i32 let users_online: u64 = 1_234_567; // big number with _ let byte_value: u8 = 255; // max u8 // byte_value = 256; // ERROR! overflow let population_hyd: usize = 10_000_000; // usize good for counts println!("Temp: {}, Users: {}, Hyd pop: {}", temperature, users_online, population_hyd); } |
Literals (ways to write numbers):
- 42 → i32
- 42i64 → i64
- 255u8 → u8
- 1_000_000 → underscore ignored, just readable
B. Floating-Point Numbers (With Decimals)
Only two types:
- f32 → 32-bit (single precision, faster, less accurate)
- f64 → 64-bit (double precision, default, more accurate)
|
0 1 2 3 4 5 6 7 8 9 10 11 |
fn main() { let pi = 3.14159; // inferred as f64 (default) let gravity: f32 = 9.81; // explicit f32 println!("Pi: {}, Gravity: {}", pi, gravity); } |
Use f64 most times unless you need smaller size (embedded, games).
C. Booleans (true / false)
Only two values: true or false
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
fn main() { let is_hot = true; let is_raining = false; if is_hot { println!("Hyderabad summer mode ON! 🔥"); } } |
Used everywhere in conditions, flags.
D. Characters (char)
- char = Unicode scalar value (not just ASCII!)
- Size: 4 bytes (can hold any emoji, Telugu letter, Chinese, etc.)
- Written in single quotes‘ ‘
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
fn main() { let letter = 'A'; let telugu = 'హ'; // Ha in Telugu! let emoji = '🦀'; // Ferris the Rust crab let space = ' '; println!("Letter: {}, Telugu: {}, Crab: {}", letter, telugu, emoji); } |
Not the same as strings — char is single character.
2. Compound Types (Grouping Multiple Values)
Rust has two primitive compound types (built-in, no extra crates needed):
A. Tuples (Fixed-size, heterogeneous — different types OK)
- Group values together
- Fixed length (can’t grow/shrink)
- Access by index .0, .1, etc. or destructuring
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
fn main() { let person: (String, u32, bool) = (String::from("Webliance"), 25, true); println!("Name: {}, Age: {}, Active: {}", person.0, person.1, person.2); // Destructuring (very common!) let (name, age, is_active) = person; println!("Destructured → Name: {}, Age: {}", name, age); // Unit tuple () = empty tuple, represents "nothing" let nothing = (); // like void in other languages } |
Great for returning multiple values from functions.
B. Arrays (Fixed-size, same type)
- All elements same type
- Length known at compile time
- Stored on stack (fast!)
- Can’t grow (use Vec<T> for dynamic)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
fn main() { let days: [&str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; println!("First day: {}", days[0]); println!("Last day: {}", days[6]); // All same value (useful!) let temperatures = [32.5; 5]; // five times 32.5 // Length println!("Array length: {}", days.len()); } |
If length unknown or needs to change → use Vec (from standard library, heap-allocated).
Quick Summary Table (Teacher Style)
| Category | Type Family | Examples | Key Points |
|---|---|---|---|
| Scalar | Integer | i32, u64, usize | Signed/unsigned, fixed sizes |
| Scalar | Float | f64 (default), f32 | Decimals, f64 most accurate |
| Scalar | Boolean | true, false | Conditions, flags |
| Scalar | Character | ‘A’, ‘🦀’, ‘హ’ | Unicode, single quotes |
| Compound | Tuple | (String, i32, bool) | Fixed, mixed types, .0 or destructuring |
| Compound | Array | [i32; 5], [“Mon”; 7] | Fixed length, same type, stack |
Practice Tip
Create a small project:
|
0 1 2 3 4 5 6 7 |
cargo new rust_types cd rust_types |
Play with all these types in main.rs, print them, try wrong assignments (see compiler errors — they are helpful!).
This covers the primitive / built-in data types. Later we add user-defined types (structs, enums), strings (String vs &str), collections (Vec, HashMap), etc.
Next ready?
- Strings in detail (&str vs String)?
- Type inference + when to write types?
- Or jump to ownership with these types?
Just tell me — your Rust journey is going strong! 🦀🚀
