Intro

Good Morro Crusty ones 😘. In todays episode of learning Rust, I will show you how to load a TOML file in Rust and additionally handle any possible errors.

Software

The following software was used in this post.

  • Rust - 1.57.0
  • toml - 0.5.2
  • serde - 1.0.136
  • serde_derive - 1.0.136

Dependencies

I will be using the toml and serde libraries for this task. The TOML library is used to manage .... you guessed it TOML files. While the serde libraries are used to serialize and deserialze data between structs and differet data formats. EG: JSON, TOML, YAML, etc...

We will need to add the TOML and serde crates to the Cargo.toml file under the dependencies section.

Cargo.toml
[dependencies]
toml = "0.5.2"
serde = "1.0.136"
serde_derive = "1.0.136"

TOML File

Now, create a TOML file named test.toml which we will be loaded into a struct.

test.toml
[config]
ip = "42.69.42.0"
port = 42

Lets Get Rusty

Add the following contents to the main.rs file. Follow along with the files comments for details of what is happening in the code.

main.rs
// Import the required dependencies.
use serde_derive::Deserialize;
use std::fs;
use std::process::exit;
use toml;

// Top level struct to hold the TOML data.
#[derive(Deserialize)]
struct Data {
    config: Config,
}

// Config struct holds to data from the `[config]` section.
#[derive(Deserialize)]
struct Config {
    ip: String,
    port: u16,
}

fn main() {
    // Variable that holds the filename as a `&str`.
    let filename = "test.toml";

    // Read the contents of the file using a `match` block 
    // to return the `data: Ok(c)` as a `String` 
    // or handle any `errors: Err(_)`.
    let contents = match fs::read_to_string(filename) {
        // If successful return the files text as `contents`.
        // `c` is a local variable.
        Ok(c) => c,
        // Handle the `error` case.
        Err(_) => {
            // Write `msg` to `stderr`.
            eprintln!("Could not read file `{}`", filename);
            // Exit the program with exit code `1`.
            exit(1);
        }
    };

    // Use a `match` block to return the 
    // file `contents` as a `Data struct: Ok(d)`
    // or handle any `errors: Err(_)`.
    let data: Data = match toml::from_str(&contents) {
        // If successful, return data as `Data` struct.
        // `d` is a local variable.
        Ok(d) => d,
        // Handle the `error` case.
        Err(_) => {
            // Write `msg` to `stderr`.
            eprintln!("Unable to load data from `{}`", filename);
            // Exit the program with exit code `1`.
            exit(1);
        }
    };

    // Print out the values to `stdout`.
    println!("{}", data.config.ip); // => 42.69.42.0
    println!("{}", data.config.port); // => 42
}

Learning Rust has been quite enjoyable for me so far and I look forward to writing more code in Rust.

Outro

In this post, I showed you how to load a TOML file in Rust and handle any errors that may arise.

Tags

rust