Structure your data in Rust

Reading Time: 3 minutes

Structuring of data in correct way is very important. In java and C++, we use Class & Object. In C, we use structures , unions, and enums.

We know that Rust adopts some features of functional programming and OOPS. Class and object is the main weapon of OOPS‘ feature but how rust provides that functionality in its context. We will see this:

As Rust is bit similar to C, so it also uses structures to structure the data.

What is Structure?

A struct, or structure, is a user-defined data type that lets you create a data type that can be used to group items of possibly different types into a single entity. There are three types of structures:

  • Classical struct
  • Tuple Struct
  • Unit Struct

How to create a classical struct?

To create and define a struct,you enter the keyword struct and name the entire struct. A struct’s name should describe the significance of the pieces of data being grouped together. Then, inside curly brackets, we define the names and types of the pieces of data, which we call fields. For example, a struct that stores information about a user account.

 struct User {
     username: String,
     email: String,
     sign_in_count: u64,
     active: bool,
 }

To use a struct after we’ve defined it, we create an instance of that struct by specifying concrete values for each of the fields. We don’t have to specify the fields in the same order in which we declared them in the struct. For example,

let user1 = User {
     email: String::from("someone@example.com"),
     username: String::from("someusername123"),
     active: true,
     sign_in_count: 1,
 };

To get a specific value from a struct, we can use dot notation. You don’t have to rely on the order of the data to specify and access the values of an instance. For example,

let mut user1 = User {
     email: String::from("someone@example.com"),
     username: String::from("someusername123"),
     active: true,
     sign_in_count: 1,
 };
user1.email = String::from("anotheremail@example.com");

Functionality of Class and Objects in Rust

The Gang of Four book, is a catalog of object-oriented design patterns. It defines OOPs this way:

Object-oriented programs are made up of objects. An object packages both data and the procedures that operate on that data. The procedures are typically called methods or operations.

Using this definition, Rust is object-oriented: structs and enums have data, and impl blocks provide methods on structs and enums. Even though structs and enums with methods aren’t called objects, they provide the same functionality, according to the Gang of Four’s definition of objects.

Functionality of Constructors in Rust

Note that the entire instance must be mutable; Rust doesn’t allow us to mark only certain fields as mutable. As with any expression, we can construct a new instance of the struct as the last expression in the function body to implicitly return that new instance. For example,

impl User {
    fn new(email: String, username: String) -> User {
        User {
            email: email,
            username: username,
            active: true,
            sign_in_count: 1,
        }
    }
}

Using the Field Init shorthand

When the parameter names and the struct field names are exactly the same, we can use the field init shorthand. For example,

fn new(email: String, username: String) -> User {
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}

Creating Instances From Other Instances

It’s often useful to create a new instance of a struct that uses most of an old instance’s values but changes some. You’ll do this using struct update syntax. For example,

let user2 = User {
    email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    active: user1.active,
    sign_in_count: user1.sign_in_count,
};

The syntax .. specifies that the remaining fields not explicitly set should have the same value as the fields in the given instance.

let user2 = User {
    email: String::from("another@example.com"),
    username: String::from("anotherusername567"),
    ..user1
};

Type of struct

1. Tuple Structs

When you want to give the whole tuple a name and make the tuple be a different type than other tuples, you can use tuple structs without named fields to create different types. For example, here are definitions and usages of two tuple structs named Color and Point:

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

2. Unit Structs

You can also define structs that don’t have any fields! Unit-like structs can be useful in situations in which you need to implement a trait on some type but don’t have any data that you want to store in the type itself. For example,

struct Nil;

I hope this blog covers all your doubts about how to structure your data in rust as compared to other programming languages. This article was first published on the Knoldus blog.

Thank You!

Written by 

Amita Yadav is a Software Consultant Trainee at Knoldus Software INC, currently working on RUST, system programming language. She is self-determined at what she has to do. She likes to learn trending technologies. She is familiar with languages such as C++, C, Java, Scala and technologies like lagom, Play, Akka, Kafka, spark, and databases like Cassandra, MySql, Sqlite, Slick. She loves to create amazing videos mashup.