Every programming language depends on data types. The same goes for Rust programming language. Rust Data Types cover the various needs of storing data. Since Rust is a statically typed language, data types become even more important. The Rust compiler uses the data types at the compilation time to make sure that the program is correct.

In case you are completely new to Rust, I will recommend you to first check out this post on introduction to Rust programming language.

Rust Data Types are divided into two major types – Scalar and Compound Types. We will look at both types in detail.

1 – The Rust Scalar Data Types

Scalar types store a single value. They are also known as primitive data types in other programming languages.

1.1 – The Integer Type

An integer is the most common scalar data type. It is basically a number without any fractional component. We can declare an integer as follows:

fn main() {
   let counter: u32 = 5;
}

In Rust, integers can be unsigned or signed. Also, the integer data type has a few variants. We can use the appropriate variant depending on our data requirements.

The below table describes the available variants:

LengthSignedUnsigned
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize
Rust Integer Data Types

The integer variants differ on the basis of size. Signed and unsigned signifies whether the number can be negative or only positive. In other words, if the number has to support a sign or not. When we expect the number to be always positive, there is no need to have a signed integer.

The signed variants can store numbers from -(2n-1) to 2n-1-1 inclusive. Basically, n is the number of bits. So, for example, the 8-bit signed integer can store numbers from -128 to 127. Also, the unsigned 8-bit variant stores numbers from 0 to 255.

The isize and usize types depend on the architecture of the computer. On a 64-bit machine, this will mean an integer with size 64-bit. On 32-bit machine, this will amount to 32 bits.

1.2 – Floating-Point Types

Rust also has two primitive types for floating-point numbers. Basically, these are numbers with decimal points.

Rust has two floating-point types. They are f32 and f64. Basically, f32 is for 32 bits and f64 is for 64 bits. On modern CPUs, the default type is f64. Also, all floating-point numbers are signed.

We can declare a floating-point number as follows:

fn main() {
   let price = 9.99; //This will be f64
   let temperature: f32 = 32.6; //This will be f32
}

1.3 – The Boolean Type

Boolean is the third important scalar type in Rust. Basically, boolean has two possible values – true and false. Also, booleans are one byte in size.

See below example on how to declare a boolean.

fn main() {
   let isAvailable: bool = false;
}

Booleans are extremely important in writing conditional statements.

1.4 – The Character Type

Rust also has a primitive alphabetic type. This is known as the char type. Basically, this type is used to declare character values.

See below:

fn main() {
   let option = 'A';
}

The char literals are specified using single quotes. This is different from string literals where we use double quotes.

Also, the char type in Rust is 4 bytes in size. It also represents Unicode Scalar Value. In other words, a char in Rust can represent a lot more than just ASCII.

2 – The Rust Compound Data Types

With scalar types out of the way, we can now look at compound types in Rust. Basically, compound types are used to group multiple values into one type.

There are a couple of primitive compound types:

2.1 – The Tuple Data Type

A tuple is a way of grouping together a number of values with a variety of types into one compound type. However, tuples have fixed length: once declared, they cannot grow or shrink in size.

Let us see how we can create a tuple.

fn main() {
   let demoTuple: (u32, f64, u16) = (525, 9.99, 2);
}

Basically, to create a tuple, we need to provide a comma-separated list of value within parantheses. Each position in the tuple has an individual type. Also, each type can be different. The type annotations shown in the above snippet are optional.

To access elements from within the tuple, we can use pattern matching to de-structure the tuple value.

See below example:

fn main() {
   let demoTuple: (u32, f64, u16) = (525, 9.99, 2);
   let (a, b, c) = demoTuple;
}

Here, the variables a, b and c will have the respective values from the tuple.

Also, we can access a tuple element directly by using period followed by the index of the value. See below example:

fn main() {
   let demoTuple: (u32, f64, u16) = (525, 9.99, 2);

   let firstNumber = demoTuple.0;
   let secondNumber = demoTuple.1;
}

We can also have a tuple without any value. This is a special type and is written as (). We also call it the unit type and the value is called unit value.

2.2 – The Array Data Type

The next way to have a collection of multiple values is by using an array. However, arrays differ from tuples in one fundamental manner. In arrays, every element must have the same data type.

We can declare an array in Rust as below:

fn main() {
   let numbers = [4, 8, 7, 3, 2];
}

Arrays in Rust have a fixed length. Also, when we declare an array, the memory is allocated on the stack rather than heap.

We should use arrays when we know the number of elements in the array will not change over time.

Array declaration can also contain the data type and the number of elements.

let numbers: [u32; 5] = [4, 8, 7, 3, 2];

We can also initialize an array with same value for each element using the below syntax:

let numbers: [1; 5];

This will create an array of 5 elements where each element will have the value 1 initially.

Since array sizes are known at compile time, Rust allocates a single chunk of memory on the stack. This allows us to access elements of the array using indexing.

For example, to access the second element in the below array, we can have use the index 1.

fn main() {
   let numbers = [4, 8, 7, 3, 2];
   let second = numbers[1];
}

The index starts from 0.

Conclusion

Rust data types cover all the use-cases a typical application may need to function properly. We have scalar data types to store individual values and compound data types to store a group of values.

If you have any comments or queries about this post, please feel free to mention them in the comments section below.

Categories: BlogRust

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *