Primitive data types

  • bool

    true or false

let x = true;
let y: bool = false;

// ⭐️ no TRUE, FALSE, 1, 0
  • char

    A single Unicode scalar value

let x = 'x';
let y = '😎';

// ⭐️ no "x", only single quotes
//because of Unicode support, char is not a single byte, but four.
  • i8, i16, i32, i64

    Fixed size(bit) signed(+/-) integer types

DATA TYPE

MIN

MAX

i8

-128

127

i16

-32768

32767

i32

-2147483648

2147483647

i64

-9223372036854775808

9223372036854775807

💡 Min and max values are based on IEEE standard for Binary Floating-Point Arithmetic; From -2ⁿ⁻¹ to 2ⁿ⁻¹-1 . You can use min_value() and max_value() to find min and max of each integer type, ex. i8::min_value();

  • u8, u16, u32, u64

    Fixed size(bit) unsigned(+) integer types

DATA TYPE

MIN

MAX

u8

0

255

u16

0

65535

u32

0

4294967295

u64

0

18446744073709551615

💡 Same as signed numbers, min and max values are based on IEEE standard for Binary Floating-Point Arithmetic; From 0 to 2ⁿ-1 . Same way you can use min_value() and max_value() to find min and max of each integer type, ex. u8::max_value();

  • isize

    Variable sized signed(+/-) integer

Simply this is the data type to cover all signed integer types but memory allocates according to the size of a pointer. Min and max values are similar to i64 .

  • usize

    Variable sized unsigned(+) integer

Simply this is the data type to cover all unsigned integer types but memory allocates according to the size of a pointer. Min and max values are similar to u64.

  • f32

    32-bit floating point

Similar to float in other languages, Single precision.

💡 Should avoid using this unless you need to reduce memory consumption badly or if you are doing low-level optimization, when targeted hardware not supports for double-precision or when single-precision is faster than double-precision on it.

  • f64

    64-bit floating point

Similar to double in other languages, Double precision.

  • arrays

    Fixed size list of elements of same data type

let a = [1, 2, 3]; // a[0] = 1, a[1] = 2, a[2] = 3
let mut b = [1, 2, 3];

let c: [i32; 0] = []; //[Type; NO of elements] -> [] /empty array
let d: [i32; 3] = [1, 2, 3];

let e = ["my value"; 3]; //["my value", "my value", "my value"];

println!("{:?}", a); //[1, 2, 3]
println!("{:#?}", a);
//  [
//      1,
//      2,
//      3
//  ]

⭐️ Arrays are immutable by default and also even with mut, its element count can not be changed.

🔎 If you are looking for a dynamic/growable array, you can use Vec. Vectors can contain any type of elements but all elements must be in the same data type.

  • tuples

    Fixed size ordered list of elements of different(or same) data types

let a = (1, 1.5, true, 'a', "Hello, world!");
// a.0 = 1, a.1 = 1.5, a.2 = true, a.3 = 'a', a.4 = "Hello, world!"

let b: (i32, f64) = (1, 1.5);

let (c, d) = b; // c = 1, d = 1.5
let (e, _, _, _, f) = a; //e = 1, f = "Hello, world!", _ indicates not interested of that item

let g = (0,); //single-element tuple

let h = (b, (2, 4), 5); //((1, 1.5), (2, 4), 5)

println!("{:?}", a); //(1, 1.5, true, 'a', "Hello, world!")

⭐️ Tuples are also immutable by default and even with mut, its element count can not be changed. Also if you want to change an element’s value, new value should have the same data type of previous value.

  • slice

    Dynamically-sized reference to another data structure

Think you want to get/pass a part of an array or any other data structure. Instead of copy it to another array (or same data structure), Rust allows to create a view/reference to access only that part of data. And it can be mutable or not.

let a: [i32; 4] = [1, 2, 3, 4];//Parent Array

let b: &[i32] = &a; //Slicing whole array
let c = &a[0..4]; // From 0th position to 4th(excluding)
let d = &a[..]; //Slicing whole array

let e = &a[1..3]; //[2, 3]
let f = &a[1..]; //[2, 3, 4]
let g = &a[..3]; //[1, 2, 3]
  • str

    Unsized UTF-8 sequence of Unicode string slices

let a = "Hello, world."; //a: &'static str
let b: &str = "こんにちは, 世界!";

⭐️ It's an immutable/statically allocated slice holding an unknown sized sequence of UTF-8 code points stored in somewhere in memory. &str is used to borrow and assign the whole array to the given variable binding.

🔎 A String is a heap-allocated string. This string is growable, and is also guaranteed to be UTF-8. They are commonly created by converting from a string slice using the to_string() or String::from() methods. ex: “Hello”.to_string(); String::from("Hello");

💡 In general, you should use String when you need ownership, and &str when you just need to borrow a string.

  • functions

    As we discussed on functions section, b is a function pointer, to plus_one function

fn plus_one(a: i32) -> i32 {
    a + 1
}

let b: fn(i32) -> i32 = plus_one;
let c = b(5); //6

Last updated