Exploring Rust Struct Types and Applications

RustRustBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we will be exploring structures in the Rust programming language. There are three types of structures ("structs") that can be created using the struct keyword: tuple structs, classic C structs, and unit structs. Tuple structs are essentially named tuples, C structs are the traditional structs found in C programming, and unit structs are field-less and useful for generics. We can define structs with multiple fields, such as Person which has name and age fields. Structs can also be reused as fields of another struct, as shown in the example of a Rectangle which consists of two Point structs representing the top left and bottom right corners. We can initialize structs using field init shorthand and access their fields using dot notation. It is also possible to destructure structs using the let binding. Additionally, the lab provides two activities - creating a function rect_area to calculate the area of a Rectangle using nested destructuring, and creating a function square that takes a Point and a f32 as arguments and returns a Rectangle with its top left corner on the point and a width and height corresponding to the f32.

Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use main.rs, compile and run it with rustc main.rs && ./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("`Rust`")) -.-> rust/BasicConceptsGroup(["`Basic Concepts`"]) rust(("`Rust`")) -.-> rust/DataTypesGroup(["`Data Types`"]) rust(("`Rust`")) -.-> rust/FunctionsandClosuresGroup(["`Functions and Closures`"]) rust(("`Rust`")) -.-> rust/DataStructuresandEnumsGroup(["`Data Structures and Enums`"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("`Variable Declarations`") rust/DataTypesGroup -.-> rust/integer_types("`Integer Types`") rust/DataTypesGroup -.-> rust/floating_types("`Floating-point Types`") rust/DataTypesGroup -.-> rust/type_casting("`Type Conversion and Casting`") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("`Function Syntax`") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("`Expressions and Statements`") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("`Method Syntax`") subgraph Lab Skills rust/variable_declarations -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} rust/integer_types -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} rust/floating_types -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} rust/type_casting -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} rust/function_syntax -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} rust/expressions_statements -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} rust/method_syntax -.-> lab-99224{{"`Exploring Rust Struct Types and Applications`"}} end

Structures

There are three types of structures ("structs") that can be created using the struct keyword:

  • Tuple structs, which are, basically, named tuples.
  • The classic C structs
  • Unit structs, which are field-less, are useful for generics.
// An attribute to hide warnings for unused code.
#![allow(dead_code)]

#[derive(Debug)]
struct Person {
    name: String,
    age: u8,
}

// A unit struct
struct Unit;

// A tuple struct
struct Pair(i32, f32);

// A struct with two fields
struct Point {
    x: f32,
    y: f32,
}

// Structs can be reused as fields of another struct
struct Rectangle {
    // A rectangle can be specified by where the top left and bottom right
    // corners are in space.
    top_left: Point,
    bottom_right: Point,
}

fn main() {
    // Create struct with field init shorthand
    let name = String::from("Peter");
    let age = 27;
    let peter = Person { name, age };

    // Print debug struct
    println!("{:?}", peter);

    // Instantiate a `Point`
    let point: Point = Point { x: 10.3, y: 0.4 };

    // Access the fields of the point
    println!("point coordinates: ({}, {})", point.x, point.y);

    // Make a new point by using struct update syntax to use the fields of our
    // other one
    let bottom_right = Point { x: 5.2, ..point };

    // `bottom_right.y` will be the same as `point.y` because we used that field
    // from `point`
    println!("second point: ({}, {})", bottom_right.x, bottom_right.y);

    // Destructure the point using a `let` binding
    let Point { x: left_edge, y: top_edge } = point;

    let _rectangle = Rectangle {
        // struct instantiation is an expression too
        top_left: Point { x: left_edge, y: top_edge },
        bottom_right: bottom_right,
    };

    // Instantiate a unit struct
    let _unit = Unit;

    // Instantiate a tuple struct
    let pair = Pair(1, 0.1);

    // Access the fields of a tuple struct
    println!("pair contains {:?} and {:?}", pair.0, pair.1);

    // Destructure a tuple struct
    let Pair(integer, decimal) = pair;

    println!("pair contains {:?} and {:?}", integer, decimal);
}

Activity

  1. Add a function rect_area which calculates the area of a Rectangle (try using nested destructuring).
  2. Add a function square which takes a Point and a f32 as arguments, and returns a Rectangle with its top left corner on the point, and a width and height corresponding to the f32.

Summary

Congratulations! You have completed the Structures lab. You can practice more labs in LabEx to improve your skills.

Other Rust Tutorials you may like