How to Use Rust Structs, Methods (Impl), and Traits With Examples | by Sung Kim | Mar, 2022

Picture by Phyllis on Unsplash

I all the time discover that when studying a programming language, it’s useful when the instance offered displays real-world use circumstances. Sadly, these sorts of examples aren’t offered or are arduous to seek out.

For instance, the “Defining and Instantiating Structs” part in The Rust Programming Language e book offers an instance the place one defines Structs after which creates an occasion of that Struct by specifying a worth for every of the fields within the code itself. In the true world, no programmer would do that for an apparent cause. It additionally doesn’t clarify how one would use Structs of their code.

Since I would like a featured picture for this text, the next is an instance of Structs.

Earlier than diving into an article, let’s get some housekeeping out of approach first by offering an outline of Structs and use circumstances for utilizing Structs in your code. All supply codes are additionally out there on GitHub => https://github.com/sungkim11/rust-struct.

A struct is a user-defined sort that we will use to retailer a number of variables of various sorts. A struct permits us to group associated code collectively and fashions our utility after entities in the true world per https://www.koderhq.com/tutorial/rust/struct/.

An instance of a struct is:

struct Consumer 
energetic: bool,
username: String,
electronic mail: String,
sign_in_count: u64,

The place would you utilize Structs?

A superb use case for utilizing structs can be calling a REST API the place the response is returned in JSON format. An instance of JSON format is:


"energetic": true
"username": "person",
"electronic mail": "person@person.com",
"sign_in_count": 2

As you’ll be able to see from above, Structs are much like JSON the place you’ll be able to map JSON values to a Struct. In the true world, structs are used to parse JSON values. It’s often referred to as Deserialize/Decode to transform JSON to struct and Serialize/Encode to transform struct to JSON.

Coinbase REST API

We might be creating an utility to get Bitcoin worth in US Greenback or BTC-USD for brief by way of Coinbase REST API (https://developers.coinbase.com/api/v2#data-endpoints).

It’s a easy utility that calls Coinbase REST API, parses REST API response then prints out BTC-USD costs.

To name Coinbase REST API, simply copy and paste the next URL to your browser:

https://api.coinbase.com/v2/prices/BTC-USD/spot

It ought to return or obtain response.json file with the next contents in JSON format for an instance, which offers each spot worth in addition to “base-currency” or “BTC-USD”.


"information":
"base":"BTC",
"forex":"USD",
"quantity":"40731.94"

Rust Crates

Earlier than we begin creating the applying, we might want to add two Rust crates:

  • Serde: It’s a framework for serializing and deserializing Rust information constructions effectively and generically. Their crates.io URL is https://crates.io/crates/serde. Serde is used to map JSON information into Rust information constructions or Struct. It’s used to Deserialize or convert JSON to struct and Serialize or convert struct to JSON.
  • Reqwest: It’s HTTP Shopper for Rust. Their crates.io URL is https://crates.io/crates/reqwest. Reqwest is used to make HTTPS requests to Coinbase REST API.

Lastly, Cargo.toml is modified to incorporate two crates as follows:

[package]
identify = "rust-struct"
model = "0.1.0"
version = "2021"
# See extra keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]
serde = model = "1.0.136", options = ["derive"]
reqwest = model = "0.11", options = ["blocking", "json"]

On this article, we are going to use real-world examples for example the next classes:

  • Lesson 1: Outline Structs
  • Lesson 2: Move Structs to Operate
  • Lesson 3: Outline Methodology (impl) to Struct
  • Lesson 4: Outline Trait to Struct
  • Lesson 5: Mix all classes

Lesson 1: Outline Structs

We outline Rust Struct by mirroring JSON information construction.

JSON (response.json)

The next JSON has a hierarchical construction or nested construction as proven under:


"information":
"base":"BTC",
"forex":"USD",
"quantity":"40731.94"

Rust Struct

Rust Struct helps nested construction by creating two structs the place the info sort of “CoinPrice” is used to copy JSON’s nested construction.

Lastly, it implements Serde’s Deserialize to map JSON information into Rust Struct. The best method to create a struct from JSON file is to goto quicktype (https://app.quicktype.io/) then copy JSON because the supply and specify Rust as a goal. I’ve modified the struct identify to fulfill my wants.

#[derive(Serialize, Deserialize, Debug)]
pub struct CoinbasePrice
pub information: CoinPrice
#[derive(Serialize, Deserialize, Debug)]
pub struct CoinPrice
pub base: String,
pub forex: String,
pub quantity: String,

REST API Request

After we outlined structs, we might want to make REST API request. That is completed by way of reqwest::Shopper, which is mirrored within the code as:

  • Creates a brand new shopper — let shopper = Shopper::new();
  • Make REST API request — let resp_spot_price = shopper.get(&spot_url).ship();

The place it assigns the response to a variable, referred to as resp_spot_price.

let spot_url = format!("https://api.coinbase.com/v2/costs/currency-rates/spot",          
forex = "BTC",
charges = "USD");
let shopper = Shopper::new();
let resp_spot_price = shopper.get(&spot_url)
.ship();

Parse REST API JSON Response

After we make a REST API request, we use

match 
Okay()
Err ()

it as a result of resp_spot_price is a worth is wrapped within the Outcome sort.

We are able to then parse the JSON response (i.e., worth) to a struct by assigning the JSON response to the variable of sort CoinbasePrice.

match resp_spot_price {        
Okay(parsed_spot_price) => {
let coinprice = parsed_spot_price.json::<CoinbasePrice>().unwrap();

Assign JSON Response to Struct

Please be aware that CoinbasePrice struct is structured as follows:

CoinbasePrice
information
base
forex
quantity

After we’ve got parsed JSON response to CoinbasePrice struct, we will assign values from CoinbasePrice struct to CoinPrice struct.

let spot_price = CoinPrice 
base: coinprice.information.base,
forex: coinprice.information.forex,
quantity: coinprice.information.quantity
;

Print Crypto Value

Lastly, print out the crypto worth utilizing CoinPrice struct, which means base = spot_price.base.

println!("SPOT: base-currency: quantity",
base=spot_price.base,
forex=spot_price.forex,
quantity=spot_price.quantity);

Accomplished Code

Lastly, the finished code is offered under the place there are two recordsdata:

  • primary.rs: It simply calls rust_struct_1 perform in rust_struct_1.rs
  • rust_struct_1.rs

The code for primary.rs is

//Lesson 1: Structs
//Declare Modules
mod rust_struct_1;
//Name Lesson 1: Structs
fn primary()
rust_struct_1::rust_struct_1();

rust_struct_1.rs:

Lesson 2: Move Structs to Operate

We elaborate on the earlier lesson so as to add a perform the place we move struct occasion to a perform.

This perform merely strikes print performance from the primary block of code to a perform to reveal how one can move struct occasion to a perform with struct identify (CoinPrice) as a parameter.

Snippet from the primary block of code :

println!("SPOT: base-currency: quantity",
base=spot_price.base,
forex=spot_price.forex,
quantity=spot_price.quantity);

Operate print_coin_price with struct identify (CoinPrice) as a parameter:

fn print_coin_price(coin_price:CoinPrice) 
println!("SPOT: base-currency: quantity",
base=coin_price.base,
forex=coin_price.forex,
quantity=coin_price.quantity);

Accomplished Code

Lastly, the finished code is offered under the place there are two recordsdata:

  • primary.rs: It simply calls rust_struct_2 perform in rust_struct_2.rs
  • rust_struct_2.rs

primary.rs:

//Lesson 2: Move Structs to Operate
//Declare Modules
mod rust_struct_1;
//Name Lesson 2: Move Structs to Operate
fn primary()
rust_struct_2::rust_struct_2();

rust_struct_2.rs:

Lesson 3: Outline Methodology (impl) to Struct

We are able to add a perform to a struct. These features are generally often called strategies and are solely out there to an occasion of a struct. To outline a way, we modified the perform print_coin_price with a wrapper of a struct (CoinPrice) utilizing key phrase impl and altered the parameter to self.

impl CoinPrice 
fn print_coinprice(self)
println!("SPOT: base-currency: quantity",
base=self.base,
forex=self.forex,
quantity=self.quantity);

Since we’ve got added a way to a struct, to name this technique, we simply use:

pot_price.print_coinprice();

Accomplished Code

Lastly, the finished code is offered under the place there are two recordsdata:

  • primary.rs: It simply calls rust_struct_3 perform in rust_struct_3.rs
  • rust_struct_3.rs

primary.rs:

//Lesson 3: Outline Methodology (impl) to Struct
//Declare Modules
mod rust_struct_1;
//Name Lesson 3: Outline Methodology (impl) to Struct
fn primary()
rust_struct_3::rust_struct_3();

rust_struct_3.rs:

Lesson 4: Outline Trait to Struct

You possibly can have a number of strategies to a struct. Traits are used to declare and group these strategies.

Outline Trait

pub trait Value 
fn format_coinprice(&self) -> String;
fn return_coinprice(&self) -> String;

Implement Trait for Struct (“CoinPrice”)

impl Value for CoinPrice 
fn format_coinprice(&self) -> String
return format!("SPOT: base-currency: quantity",
base=self.base,
forex=self.forex,
quantity=self.quantity);

fn return_coinprice(&self) -> String
return format!("SPOT: quantity",
quantity=self.quantity);

Name Struct (“CoinPrice”) strategies in a Trait

println!("", spot_price.format_coinprice());
println!("", spot_price.return_coinprice());

Accomplished Code

Lastly, the finished code is offered under the place there are two recordsdata:

  • primary.rs: It simply calls rust_struct_4 perform in rust_struct_4.rs
  • rust_struct_4.rs

primary.rs:

//Lesson 4: Outline Trait to Struct
//Declare Modules
mod rust_struct_1;
//Name Lesson 4: Outline Trait to Struct
fn primary()
rust_struct_4::rust_struct_4();

rust_struct_4.rs:

Lesson 5: Mix all classes

Lastly, we mix all earlier classes to implement Structs, Strategies (Impl), and Traits. The code has been modified to include all Coinbase Value Information API to print out BTC-USD costs for SPOT, BUY, and SELL in addition to the SPREAD between BUY and SELL in a single line.

The finished code is offered under the place there are two recordsdata:

  • primary.rs: It simply calls rust_struct_5 perform in rust_struct_5.rs
  • rust_struct_5.rs

primary.rs:

//Lesson 5: Mix all classes
//Declare Modules
mod rust_struct_1;
//Name Lesson 5: Mix all classes
fn primary()
rust_struct_5::rust_struct_5();

rust_struct_5.rs:

I hope this text was useful! Thanks for studying.

More Posts