Rust Cookbook

4.3 (6 reviews total)
By Vigneshwer Dhinakaran
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Let us Make System Programming Great Again

About this book

If you are building concurrent applications, server-side programs, or high-performance applications, you will benefit from this language. This book comes with a lot of application-specific recipes to kick-start your development of real-world high-performance applications with the Rust programming language and integrating Rust units into your existing applications. In this book, you will find some 80 practical recipes written in Rust that will allow you to use the code samples right away in your existing applications. These recipes have been tested with stable rust compiler versions of 1.14.0 and above.

This book will help you understand the core concepts of the Rust language, enabling you to develop efficient and high-performance applications by incorporating features such as zero cost abstraction and better memory management.

We’ll delve into advanced-level concepts such as error handling, macros, crates, and parallelism in Rust. Toward the end of the book, you will learn how to create HTTP servers and web services, building a strong foundational knowledge in server-side programming and enabling you to deliver solutions to build high-performance and safer production-level web applications and services using Rust.

Publication date:
July 2017
Publisher
Packt
Pages
320
ISBN
9781785880254

 

Chapter 1. Let us Make System Programming Great Again

In this chapter, we will cover the following recipes:

  • Setting up Rust in Linux and macOS
  • Setting up Rust in Windows
  • Creating your first Rust program
  • Defining a variable assignment
  • Setting up Boolean and the character types
  • Controlling decimal points, number formats, and named arguments
  • Performing arithmetic operations
  • Defining mutable variables
  • Declaring and performing string operations
  • Declaring arrays and using slices in Rust
  • Declaring vectors in Rust
  • Declaring tuples in Rust
  • Performing calculations on two numbers
 

Introduction


This chapter is focused on bringing about a behavioral change in you in regard to setting up Rust and programming with it. The objective of this chapter is to make you realize why one should use Rust when there are so many other programming languages out there solving various problems in different verticals--why is there a need for yet another programming language?

These are the fundamental questions that would come to one's mind when they are learning a new language, well Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety. As the definition mentions Rust is focused towards eliminating a various class of system programming bugs and errors which at the end of the day helps in making secure, faster, and out-of-the-box production grade applications.

This chapter dives deeper into various assignment operations and their features, data types, and data structures in Rust.

 

Setting up Rust in Linux and macOS


We will explore ways in which we can install Rust components in Linux and macOS operating systems and also cover the different problems faced during the installation.

Getting ready

In order to run Rust code in your workstations, we have to install the Rust compiler. We require Unix-based operating systems such as Linux distributions and macOS.

How to do it...

Follow these steps to set up Rust on your system:

  1. Open the Terminal.

Note

In macOS, you can open the Terminal by pressing the F4 key, which opens the launchpad and searches for the Terminal. Then, you can select the Terminal option in the display. This is just one possible way of doing it; there are other ways too. In Linux distributions, we can jointly press Ctrl + Alt + T to open the Terminal or search for it in the application search window.

 

  1. Type the following command to install the Rust compiler and Cargo in your system:
      curl https://sh.rustup.rs -sSf | sh

You can also try using the following command:

      curl -sf https://static.rust-lang.org/rustup.sh | sudo sh

The preceding commands will start the installation, and as it proceeds, the script will require user input. Enter for the default installation, which is the standard way. After this step, different components will be downloaded. If the installation happens without any error, you should be able to see the following screenshot:

Rust is installed now. Great!

Uninstalling Rust

Uninstalling Rust is as easy as installing it. Open the Terminal and type the following command:

rustup self uninstall

Rust's compiler version

If you have reached here, you have got Rust installed on your system, and you can go ahead and verify it. Open up the Terminal and enter the following command, which will give you the version of Rust installed:

rustc --version

Take a look at the following screenshot:

Here, rustc stands for the Rust compiler and --version displays the Rust version we have downloaded. By default, the rustup.sh script downloads the latest stable build. In this book, we are working with the 1.14.0 version.

Congrats, if you have reached this step without any error! Rust has been installed successfully.

Advanced installation options

A few other commands with the rustup.sh script are as follows. These commands are not necessary for common usage. The following commands are advanced commands that are not usually used by developers at an early stage of Rust development.

  1. Install to a particular location:
      rustup.sh prefix=my/install/dir
  1. Save the download for faster reinstallation:
      rustup.sh save
  1. Install nightly:
      rustup.sh channel=nightly
  1. Install nightly archives:
      rustup.sh --channel=nightly date=2015-04-09
  1. Install the explicit versions:
      rustup.sh --revision=1.0.0-beta

These commands help with the installation of a particular build, unstable releases, and version-controlled component installation.

Troubleshooting

If you try to reinstall Rust after its uninstallation, you'll often get an error saying that rustup.sh already exists. Please refer the following screenshot:

To solve the error, just delete the .rustup executable file from the user space:

rm -rf /home/viki/.rustup

If the version command doesn't work for you, then you probably have the PATH environment variable wrong and have not included Cargo's binary directory, which is ~/.cargo/bin on Unix and %USERPROFILE%\.cargo\bin on Windows.

This is the directory where Rust development tools are present, and most Rust developers keep it in their PATH environment variable, which makes it possible for them to run rustc on the command line.

Due to the differences between operating systems, command shells, and bugs in the installation, you may need to restart your shell, log out of the system, or configure PATH manually as appropriate to your operating environment.

Note

Rust does not do its own linking, so you'll need to have a linker installed. Doing so will depend on your specific system. For Linux-based systems, Rust will attempt to call cc for linking. On Rust built on Windows with Microsoft Visual Studio, this depends on having Microsoft Visual C++ Build Tools installed. These do not need to be in %PATH%, as rustc will find them automatically. In general, if you have your linker in a non-traditional location, you can call rustc linker=/path/to/cc, where /path/to/cc should point to your linker path.

If you are still stuck, there are a number of places where you can get help. The easiest is the #rust--beginners IRC channel for general discussion, and the #rust IRC channel, which we can access through Mibbit. Other great resources include the Rust user's forum and Stack Overflow.

How it works...

The shell script rustup.sh is a great way to install Rust and has been used by many developers to not only install Rust, but also Cargo on their machines.

The working of this script is pretty straightforward, where the code of the bash script hosted on the rustup server is downloaded on the host system and run automatically by passing the script code to the pipe symbol. The script offers you various installation options through which you can choose the version and type of Rust compiler you want to install. We have the nightly version, which is not the stable one, in Rust's nightly version. This version is used by developers and contributors to test and develop features for their existing projects.

 

Setting up Rust in Windows


This recipe covers how to set up Rust on a Windows system.

Getting ready

We will require a Windows machine for this purpose.

How to do it...

It is very easy to install it on Windows:

  1. Download and run the .exe file from https://win.rustup.rs.
  2. Click on the downloaded executable; this will start the installation in a Command Prompt.
  3. Select option 1 in the Command Prompt for regular installation, which is recommended.

How it works...

It's similar to Linux and macOS; we have to download the executable and run it, which pops up the Command Prompt where the installation starts. Here, instead of using the shell script, the Rust team provides an executable file for Windows. The executable downloads the Rust compiler and Cargo dependencies on your host system.

 

Creating your first Rust program


This recipe is to help you make sure that your compiler is working right and also create a workspace where you can try out all these recipes.

Getting ready

We will require the Rust compiler setup on the host system for programming; I suggest you download a text editor of your choice for this. In this book, we are using the Sublime Text editor for the code development process.

How to do it...

  1. Create a folder in your user space where you will be storing all the programs of the book:
      mkdir /home/viki/rust_cookbook
  1. This command will create a directory for you in your user space:
      cd /home/viki/rust_cookbook

The preceding commands will take us to the particular directory.

  1. Now, make a file named sample.rs; the .rs extension indicates that it is a Rust script.
  2. Open the script in your text editor and enter the following code:
        fn main() {
          println!("Welcome to Rust Cookbook");
        }
  1. Save the file and go to your Terminal.
  2. Compile the code with the Rust compiler, which will create the executable and run in a system without Rust on it:

How it works...

Let's go through the code in brief and understand how it is being executed. The Rust compiler looks for the main function, which is the starting part of the code flow. We have a print statement and the dialogue to be displayed. When we compile the code, an executable is created which on execution will print the dialogue.

Rust files always end in a .rs extension. If you have to use more than one word in your filename to represent your project it is recommended to use an underscore to separate them for example, we would use my_program.rs rather than myprogram.rs, this helps in improving readability.

The keyword fn defines a function in Rust. The main function is the beginning of every Rust program. In this program, we have a main function which does not take any input arguments and returns any type. In case of any arguments, it would go in the parentheses ( and ). The function body is wrapped in curly braces { and }. Rust requires these around all function bodies.

Note

It's considered good style to put the opening curly brace on the same line as the function declaration, with one space in between.

The println! macro in the std Rust crate is used for printing to the standard output, with a newline. Which is inside the body of the main function and prints the string Welcome to Rust Cookbook. The line ends with a semicolon (;). Rust is an expression-oriented language, which means that most things are expressions, rather than statements. The semicolon(;) indicates that this expression is over, and the next one is ready to begin.

Before running a Rust program, we have to compile it post which we can use an executable file to run the program and print the string in the terminal. The Rust compiler by entering the rustc command and passing it the name of your source file will create the executable, for example, rustc main.rs would create an executable ./main. in the same directory.

 

Defining a variable assignment


We will dive deeply into the various assignment operators and functions in this section.

Getting ready

We would require the Rust compiler and any text editor for coding and create a file named assignment.rs in the project workspace.

How to do it...

  1. Start by declaring the different libraries we would be using for this recipe in the assignment.rs script:
        // Primitive libraries in rust
        use std::{i8,i16,i32,i64,u8,u16,u32,u64,f32,f64,isize,usize};
        use std::io::stdin;

The use statement tells the compiler that the program would use the following properties of the library. The std is an inbuilt library that comes along with the Rust compiler and doesn't need to be externally downloaded. i8 and i16 are different data types of the variable that will be used in the program, and stdin helps us accept user input from the user:

        fn main() {
          println!("Understanding assignment");
          // Compiler will automatically figure out the data type if
          not mentioned
          // Cannot change the value
          let num =10;
          println!("Num is {}", num);
        }
  1. The output of the preceding script is as follows:
  1. Replace the main function of the preceding script in assignment.rs file with the following code snippet below:
        fn main(){
          let age: i32 =40;
          println!("Age is {}", age);
          // Prints the max and min value of 32bit integer
          println!("Max i32 {}",i32::MAX);
          println!("Max i32 {}",i32::MIN);
        }
  1. In the previous code snippet, we declared a variable named age and explicitly told the compiler that it's a 32-bit integer type data and that we are printing the maximum and minimum values of the 32-bit int data type. Now, the next piece of code:
        // Another way of variable assigning
        let(f_name,l_name)=("viki","d");
        println!("First name {0} and last name {1}",f_name,l_name);

Here, we have declared two variables in f_name and l_name using brackets(). This is a way to declare multiple variables in a single statement in Rust. Similarly, while printing them, we can number the position of the variable to determine which variable has to be printed first.

How it works...

In the previous section, we declared the main function from where the execution would start. Here, we are declaring a variable named num and assigning it to a value of 10. The let statement enables you to declare variables and assigns them to a value. We are not explicitly telling what kind of data type the num variable is, but during compilation time, it will be automatically determined and memory will be assigned based on that.

The num value is immutable, which means that its value cannot be changed during the program, and it will be removed from the memory once it goes out of the scope of the main function. To print the value of the number, we have to use braces; we will cover more of this in detail in the next section.

 

Setting up Boolean and the character types


Boolean operators are of great help to programmers for state identification and checking. In this recipe, you will learn about the assignment of character type variables.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named boolean.rs and compile the following code:
        fn main(){

          //Setting boolean and character types
          let bool_val: bool = true;
          let x_char: char = 'a';

          // Printing the character
          println!("x char is {}", x_char);
          println!("Bool value is {}", bool_val);
        }
  1. In the preceding code snippet, we are assigning a Boolean type variable and character values in Rust.
  2. The output is as follows:

How it works...

In the preceding code snippet, we declared the main function where we defined two variables: bool_val and x_char. We assigned them with a Boolean and character value using the let statement. We followed this up by printing them.

 

Controlling decimal points, number formats, and named arguments


This recipe focuses on how to manipulate the print macros to perform various control operations in the data.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Enter the following code in a Rust script named decimal.rs and compile them:
        fn main(){

          // Prints the first 2 numbers after the decimal points
          println!("{:.2}",1.2345 );
          println!("================");

          // print the binary hex and octal format
          println!("B: {:b} H: {:x} O: {:o}",10,10,10 );
          println!("================");

          // Shifts
          println!("{ten:>ws$}",ten=10, ws=5 );
          println!("{ten:>0ws$}",ten=10, ws=5 );
        }

2. The output of the code is as follows:

How it works...

In the first print statement, we controlled the number of decimal points to be displayed in the Terminal. In the preceding code snippet, we set the value to be two after the colon symbol (:) in the print statement, which tells the compiler to only print the first two decimal points of the variable in the runtime.

The next print statement displayed Rust's built-in feature that can convert the value to be printed in a different number format. We printed the binary, hex, and octal value of the decimal value 10. To perform this activity, we specifically mentioned the parameter after the colon symbol in the print statement. This is understood by the Rust compiler. At runtime, Rust would automatically convert the decimal type into the mentioned number format, where b stands for binary, x for hex, and o for octal. This has to be given after : in the print statement.

Next, the print statement named arguments and we defined the white space (ws) type we wanted to. We have two arguments here: ten and ws. We had control over how we wanted to print the data and what kind of values we wanted to fill ws with. In the first print statement, we filled it with blank spaces. In the second print statement, we explicitly mentioned zero, which is what we want to fill the gaps with. We declared the named argument inside the curly braces of the print statement and assigned its data value.

 

Performing arithmetic operations


This recipe showcases the different types of arithmetic operations in Rust.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named arithmetic.rs in the workspace and compile the following code:
        fn main(){
          // Arithmetic Operations
          println!("5 + 4 = {}", 5+4 );
          println!("5 - 4 = {}", 5-4 );
          println!("5 * 4 = {}", 5*4 );
          println!("5 / 4 = {}", 5/4 );
          println!("5 % 4 = {}", 5%4 );

          // Assigning data types and mathematical Operations
          let neg_4 = -4i32;
          println!("abs(-4) = {}", neg_4.abs() );
          println!("abs(-4) = {}", neg_4.pow(2) );
          println!("round(1.2345) = {}", 1.2354f64.round() );
          println!("ceil(1.2345) = {}", 1.2345f64.ceil() );
          print!("sin 3.14 = {}", 3.14f64.sin() );
        }

2. We would get the following output:

How it works...

In the first set of print statements, we have different types of arithmetic operations being performed on the data set during runtime. The following symbols in the brackets associated with each operation are used to perform the arithmetic operation:

  • addition (+)
  • subtraction (-)
  • multiplication (x)
  • division (/)
  • modulus (%)

In the next set of print statements, we performed various mathematical operations, which come built in with the Rust compiler. We declared a variable named neg_4 and assigned it the value 4i32, which is a negative 32-bit integer with the value 4. We set the absolute value of the variable by calling the abs() function with the variable name variable.function. Similarly, we performed other mathematical operations, such as pow(value), which calculates and applies the power value to the data. The round() function finds the data to the nearest lower value. The ceil() function returns the smallest integer that is greater than or equal to the number. And, the sin() functions return the sine value.

 

Defining mutable variables


Rust has the unique feature of ownership and borrowing that enables it to overcome segfaults and data races. This is achieved by the mutability property of Rust.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named mutuable.rs and compile the following code:
        fn main(){
          let mut sample_var = 10;
          println!("€œValue of the sample variable is {}",sample_var);
          let sample_var = 20;
          println!("New Value of the sample variable is {}",sample_var);
        }
  1. You should get the following output:

How it works...

Since we have declared the variable type mutable, the Rust compiler allows the developer to change the data value assigned any number of times in the scope of the functions.

In the preceding program, we created a variable named sample_var and explicitly marked it as mutable type during its assignment. Due to this action, the Rust compiler allows the variables to be assigned different values.

 

Declaring and performing string operations


This recipe dives deeply into various built-in string operations and functions that let the developer split and modify string data.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a script named string.rs and compile the following code:
        fn main() {
          // declaring a random string
          let rand_string = "I love Rust cookbook <3";

          // printing the length of the string
          println!("length of the string is {}",rand_string.len() );
  1. Here, you are creating an immutable variable called rand_string and assigning it with a string value. You are also using the len() function of the string data type to print the length of the sentence, which would also count the white space:
        // Splits in string
        let (first,second) = rand_string.split_at(7);
        println!("First part : {0} Second part : {1}",first,second);

 

  1. The split_at(value) function divides the sentence into two parts and assigns them as two variables: first and second. We then print them:
        // Count using iterator count
        let count = rand_string.chars().count();
        print!("count {}",count );
  1. We are using two functions here, namely chars and count, where chars identifies all the characters and count gives the aggregated number of characters:
        println!("__________________________");
        // printing all chars
        let mut chars = rand_string.chars();
        let mut indiv_chars = chars.next();
        loop {
          // Its like switch in c++
          match indiv_chars {
            Some(x) => println!("{}",x ),
            None => break
          }
          indiv_chars = chars.next();
        }
  1. In the preceding piece of code, we created a variable named chars, which has all the characters of the sentence. Then, in the next step, we created another variable named indiv_chars, which contains the first character of the chars variable. We used the next() functions to assign the value to indiv_chars.
  2. In the loop function, print all the values of the chars variable until it becomes null:
        println!("__________________________");
        // iterate over whitespace
        let mut iter = rand_string.split_whitespace();
        let mut indiv_word = iter.next();
        loop {
          // Its like switch in c++
          match indiv_word {
            Some(x) => println!("{}",x ),
            None => break
          }
          indiv_word = iter.next();
        }
  1. In this section of the code, we will iterate over the using the built-in split_whitespace() function. This section would print the complete words:
        println!("__________________________");
        // iterate over next line
        let rand_string2 = "I love \n everything about \n Rust <3";
        let mut iter_line = rand_string2.lines();
        let mut indiv_sent = iter_line.next();
        loop {
          // Its like switch in c++
          match indiv_sent {
            Some(x) => println!("{}",x ),
            None => break
          }
          indiv_sent = iter_line.next();
        }
        }
  1. In this section of the code, we will iterate over the next line using the built-in lines() function. This section would print the complete sentence.
  2. You should get the following result:

How it works...

In this recipe, we assign a variable named rand_string with a string value of I love Rust cookbook in which we perform a certain set of string operations.

In the first print statement, we display the length of the string by the len() method of the str type by calling rand_string.len() and correspondingly in the next print statement we use the split_at() method which expects an input argument which splits the string at the value of the argument passed and in our case we call rand_string.split_at(7) to split at index 7 of the string and assign it to the two variables named first and second, here space occupies an index value.

In the third print statement, we print the numbers of characters present by using the chars() and count() methods, we do it with the following syntax rand_string.chars().count() where chars() iterates through the characters and count() for counting the number of elements.

The loop is an iterative statement that keeps on running until the break key is called. We used the match function, which is similar to switch in other languages. We created different conditions for it to check and perform certain actions.

In the match statements, we have two conditions which are Some(x) and None. In both the cases, we perform unique operations which are as follows:

  • In the case of Some(x), it basically says that x is a value that exists and has a type T so we can use the x variable for further operations and in such cases, we print the value
  • In the case of None, it refers to cases where a value does not exist which ideally is the end of the string and the operation we perform at these cases are to break the loop

We iterate over three types of conditions:

  • The first set is individual cases, where we print all the characters of the string and is performed by the chars() and next() functions with the preceding match statements
  • The second set is where we print all the different words of the string by splitting in the places of white spaces and is performed by the split_whitespace() and next() functions with the preceding match statements
  • The last ones where we print all the different lines of the string by splitting in the places of next line and is performed by the lines() and next() functions with the preceding match statements
 

Declaring arrays and using slices in Rust


An array is a collection of objects that are of the same data type and is stored in contiguous memory. Arrays are always created using brackets [], and their size is known at compile time. It is part of their type: [T; size].

Slices are similar to arrays but their size is not known at compile time. The first mark is a pointer value to the data; the second mark is the length of the slice that is selected by the user depending on the application. Slices are usually used to borrow a section of an array and have the type signature and [T].

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named array.rs and compile the following code:
        fn main() {
          // Defining an array
          let rand_array = [1,2,3];
          println!("random array {:?}",rand_array );

          // indexing starts with 0
          println!("random array 1st element {}",rand_array[0] );
          println!("random array length {}",rand_array.len() );

          // last two elements
          println!("random array {:?}",&rand_array[1..3] );
        }

2. We would get the following output:

How it works...

Here, we declared a variable named rand_array and assigned it to an array that has three elements inside square brackets: one, two, and three. In the first print statement, we had a question mark (?) after the colon (:), which indicates to the print statement that it would print all the elements of the array.

We can address each element of the array by the indices (which refer to the position of the array data element). In Rust, the positioning starts from zero. So when we print rand_array[0], it will print the first element. In the third print statement, we used the len() function to get the length or the number of elements in the array; we used the length function by calling rand_var.len().

In the fourth print, we had a new concept called slices. Arrays are borrowed as slices, where we mention the starting value of the pointer and length in the signature. Slices basically reference to a contiguous sequence of the element of the array instead of the whole element.

We printed the complete array by printing &rand_var, which would print the total array. We also borrowed a section of array using &rand_var[1..3], where we mention the size of the slice in square brackets. Here, starting from one, we print all the sections of the numbers until the upper limit of three where one and three are the index values of the arrays which were dereferenced and printed in the Terminal.

 

Declaring vectors in Rust


Vector is a very important concept in programming and often people get confused between arrays and vectors. Let's demystify the concept. A vector is a dynamic array, which implies that its data allocation can be increased or decreased at runtime, and we will see how this can be done with a simple built-in function. Vectors are implemented in Rust as standard library types, namely Vec<T>. Here, T means that we can have vectors of any data type; vectors always allocate their data on the heap and we can create them with the vec! macro.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named vector.rs and compile the following code:
        fn main() {
          // declaring a vector
          let mut vec1 = vec![1,2,3,4,5];
  1. Declare a mutable vector vec1 with five elements:
        // printing element 3 in vector
        println!("Item 3 : {}", vec1[2]);

Here, to print the third element of the vector, we can refer to the particular data of the vector in the heap by its position.

  1. The value of the position starts from zero and goes until n-1 if there are n data values:
        // iterating in a vector
        for i in &vec1 {
          println!("{}",i )
        }
  1. In the previous step, we iterated over the vector by taking reference of the vector and printing all its elements:
        // push an element to vector
        vec1.push(6);
        println!("vector after push {:?}", vec1 );

        // pop an element from vector
        vec1.pop();
        println!("vector after pop {:?}", vec1 );
        }
  1. Add and remove the values from the vector.
  2. You should get the following output:

How it works...

We cannot use the vector again if we have iterated by taking ownership of the vector, and for reiterating the vector many times, we have to take a reference to the vector.

Using pop and push, we can add/remove elements to/from the heap of the memory allocation, where the vector data is stored. This feature allows the vector to be dynamic. ush adds a new element to the top, which is the last element of the indices, and pop removes the first value and last element with respect to the indices.

 

Declaring tuples in Rust


A tuple is a unique data structure and is widely used by many developers in their day-to-day development for processing values of different data types.

Generally, tuples are constructed by parentheses (), and each tuple has a type signature, such as T1, T2, ..., where T1 and T2 are the types of its member values.

Tuples are very handy in Rust when we want to return multiple data types. We can use Rust to package them into a single data structure.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named tuple.rs and compile the following code:
        use std::{i8};
        fn main() {

          // Declaring a tuple
          let rand_tuple = ("Rust", 2017);
          let rand_tuple2 : (&str, i8) = ("Viki",4);

          // tuple operations
          println!(" Name : {}", rand_tuple2.0);
          println!(" Lucky no : {}", rand_tuple2.1);
        }

2. You should get the following output:

How it works...

In the previous section, we declared two tuples in two different ways. In the first method, the Rust compiler automatically located the data types. In the second method, we explicitly mentioned the data types and the tuples allowed us to create different data types.

In the tuple operation section, we extracted values from the tuple using tuple indexing, which is performed by printing tuple_variable.index_value.

 

Performing calculations on two numbers


This recipe covers all the aspects that we have learned from other recipes. We perform various operations, such as entering two values from the Terminal to be accepted as standard input by the user, converting the string that is acceptable to the integer, and performing arithmetic operations.

Getting ready

We would require the Rust compiler and any text editor for coding.

How to do it...

  1. Create a file named calculator.rs and compile the following code:
        // Libraries in rust
        use std::io;
        use std::{i32};
  1. The io function helps us accept user input in the Terminal:
        // Main Functions
        fn main() {
          // Request for entering number 1
          println!("Enter First number ? ");
          let mut input1 = String::new();
          io::stdin().read_line(&mut input1).expect("Failed to read
          line");

          // Request for entering number 2
          println!("Enter second number ? ");
          let mut input2 = String::new();
          io::stdin().read_line(&mut input2).expect("Failed to read
          line");

          // Converting string to integer
          let aint: i32 = input1.trim().parse().ok().expect("Program
          only
          processes numbers, Enter number");
          let bint: i32 = input2.trim().parse().ok().expect("Program
          only
          processes numbers, Enter number");

          // Output of basic operations
          println!("sum is: {}", aint + bint);
          println!("difference is: {}", aint - bint);
          println!("Multiply is: {}", aint * bint);
          println!("division is: {}", aint / bint);
        }
  1. You should get the following output:

How it works...

The std::io module contains a number of common things you'll need when. The core part of this module is the read and write traits.

We called the read_line() method from the std::io module. The read_line() method doesn't take a String as an argument; it takes a &mut String. Rust has a feature called references, which allows you to have multiple references to one piece of data, which can reduce copying. The job of read_line is to take what the user types as standard input and place it into a string. So it takes that string as an argument, and in order to add the input, it needs to be mutable. In this case, io::Result had an expect() method that took a value it was called on; if this isn't successful, our program will crash, displaying a message. If we do not call expect(), our program will compile but we'll get a warning.

For converting the string into an integer, we used trim and parse methods. The trim() method on the strings eliminates any ws at the beginning and end of the data. This means that if we type 5 and hit return, guess it would look like this: 5\n. The \n represents a newline, the enter key induced newline will be got rid by trim() method, leaving behind our string with only the number 5.

The parse() method on string data parses a string into some kind of number format, since it can parse a variety of numbers, we need to give Rust a hint as to the exact type of number format we want it to convert, that is the reason why we have the statement let a_int: i32. The colon (:) after tells Rust we're going to annotate its type, i32 is an integer containing 32-bit size. We used the expect() method to capture a crash in the cases of an error. The last section of the script was used to conduct regular arithmetic operations.

About the Author

  • Vigneshwer Dhinakaran

    Vigneshwer Dhinakaran is an innovative data scientist with an artistic perception of technology and business, having over 3 years of experience in various domains, such as IOT, DevOps, computer vision, and deep learning, and is currently engaged as a research analyst crunching real-time data and implementing state-of-the-art AI algorithms in the innovation and development lab of the world’s largest decision science company in Bengaluru, India.

    He is an official Mozilla representative and Techspeaker in India and has been associated with Mozilla communities and technologies for more than 5 years. He has delivered various sessions on Rust language at many meetups and conferences; some of the highlighted events are Hong Kong Open Source Conference, FOSSMeet 17, and RainOfRust Campaign. He has played a key role in the formation and growth of the Rust community in India and was part of the Mozilla Reps mobilizer experiment, where he researched about the roadblocks and solutions to drive developers to adopt the Rust language in India.

    Browse publications by this author

Latest Reviews

(6 reviews total)
Très utile; à lire avec un autre livre de la série.
see my previous remark, I don't want to rate every book seperately
Interessante per l'applicazione pratica di quanto appreso.

Recommended For You

Book Title
Access this book, plus 8,000 other titles for FREE
Access now