RustでTOMLを読み込む

toml-rsで、以下のPerson.tomlを読み込みます。

# Person.toml
[profile]
name = "Alice"
age = 20

準備

toml-rsに加えて、 DeserializeにSerdeを使うので、Cargo.tomlに以下を追記します。

# Cargo.toml
[dependencies]
serde = "1.0"
serde_derive = "1.0"
toml = "0.4"

実装

パースは、toml::from_str()でできるので、パースするための構造体を定義します。 今回は、読み込み元のtomlファイルに値が存在しないことを考慮して、Optionにしましたが、確実に値が存在するのであれば、Optionにしないのもありだと思います。(参照するときにunwrap()だらけになりそうなので...)

#[derive(Debug, Deserialize)]
struct Person {
    profile: Option<Profile>,
}

#[derive(Debug, Deserialize)]
struct Profile {
    name: Option<String>,
    age: Option<i32>,
}

ファイル読み込みからパースまでの実装です。

#[macro_use]
extern crate serde_derive;
extern crate toml;

use std::fs;
use std::io::{BufReader, Read};

#[derive(Debug, Deserialize)]
struct Person {
    profile: Option<Profile>,
}

#[derive(Debug, Deserialize)]
struct Profile {
    name: Option<String>,
    age: Option<i32>,
}

fn read_file(path: String) -> Result<String, String> {
    let mut file_content = String::new();

    let mut fr = fs::File::open(path)
        .map(|f| BufReader::new(f))
        .map_err(|e| e.to_string())?;

    fr.read_to_string(&mut file_content)
        .map_err(|e| e.to_string())?;

    Ok(file_content)
}

fn main() {
    let s = match read_file("./Person.toml".to_owned()) {
        Ok(s) => s,
        Err(e) => panic!("fail to read file: {}", e),
    };

    let person: Result<Person, toml::de::Error> = toml::from_str(&s);
    match person {
        Ok(p) => println!("{:#?}", p),
        Err(e) => panic!("fail to parse toml: {}", e),
    };
}

 実行

以下のようにパースできます。

❯ cargo run
Person {
    profile: Some(
        Profile {
            name: Some(
                "Alice"
            ),
            age: Some(
                20
            )
        }
    )
}

References