TOML (Tom's Obvious, Minimal Language) is a configuration file format designed to be easy to read due to its clear semantics. Its primary goal is to be a minimal configuration file format that maps cleanly to a hash table (or dictionary) structure. It was created by Tom Preston-Werner, one of the co-founders of GitHub.
Key features and characteristics of TOML include:
* Human-readable and Easy to Write: TOML's syntax is straightforward and intuitive, making it easy for humans to read and write configuration files without significant effort or specialized tools.
* Strongly Typed: TOML supports various data types, including strings, integers, floats, booleans, datetime objects (local, offset, and local date/time), arrays, and tables (analogous to objects or dictionaries). This type safety helps prevent configuration errors.
* Hierarchical Structure: Configurations are organized into tables, which are similar to sections in INI files or objects in JSON. Tables can be nested to create hierarchical structures using dot notation or explicit `[table]` headers.
* Arrays: TOML supports arrays of primitive types and tables, allowing for lists of configurations.
* Comments: TOML allows single-line comments starting with `#`, which improves documentation within configuration files.
* Minimalism: TOML strives for minimalism, providing just enough features to represent configuration data effectively without becoming overly complex or verbose.
Compared to other popular configuration formats:
* JSON: TOML is often considered more human-friendly for manual editing than JSON due to less strict quoting rules for keys and fewer braces/brackets.
* YAML: TOML is generally less verbose and has a simpler specification than YAML, making it easier to parse and often preferred for simpler configurations where YAML's advanced features (like anchors, aliases) are not needed.
* INI: TOML can be seen as a more modern and type-safe successor to INI files, offering better support for nested structures and a wider range of data types.
TOML is widely used in the Rust ecosystem, most notably for the `Cargo.toml` file, which defines Rust project metadata and dependencies. For Rust applications, the `toml` crate, often used in conjunction with `serde` (for serialization/deserialization), provides robust functionality for parsing TOML files into Rust structs and vice-versa.
Example Code
// Cargo.toml dependencies:
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// toml = "0.8"
use serde::{Deserialize, Serialize};
use std::fs;
// Define a Rust struct that will map to our TOML configuration
#[derive(Debug, Deserialize, Serialize)]
struct Config {
title: String,
owner: Owner,
database: Database,
servers: Servers,
}
#[derive(Debug, Deserialize, Serialize)]
struct Owner {
name: String,
dob: Option<toml::value::Datetime>, // Using Option for optional fields
}
#[derive(Debug, Deserialize, Serialize)]
struct Database {
server: String,
ports: Vec<u16>,
connection_max: u32,
enabled: bool,
}
#[derive(Debug, Deserialize, Serialize)]
struct Servers {
alpha: ServerInfo,
beta: ServerInfo,
}
#[derive(Debug, Deserialize, Serialize)]
struct ServerInfo {
ip: std::net::IpAddr, // Example of using standard library types
dc: String,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// --- 1. Parsing TOML from a string ---
let toml_content = r#"
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First-party date/time type
[database]
server = "192.168.1.1"
ports = [ 8001, 8002, 8003 ]
connection_max = 5000
enabled = true
[servers]
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
"#;
println!("--- Parsing TOML content ---");
let parsed_config: Config = toml::from_str(toml_content)?;
println!("Parsed config: {:#?}", parsed_config);
// --- 2. Modifying and serializing a Rust struct to TOML ---
println!("\n--- Modifying config and serializing to TOML ---");
let mut new_config = parsed_config;
new_config.owner.name = "Jane Doe".to_string();
new_config.servers.alpha.dc = "us-east-1".to_string();
new_config.database.ports.push(8004);
let serialized_toml = toml::to_string_pretty(&new_config)?;
println!("Serialized TOML:\n{}", serialized_toml);
// --- 3. Example of writing to a file (optional) ---
// In a real application, you might write this to a file.
let file_path = "config.toml";
fs::write(file_path, serialized_toml)?;
println!("\nConfiguration written to '{}'", file_path);
// You could then read it back to demonstrate file parsing
let read_from_file_content = fs::read_to_string(file_path)?;
let config_from_file: Config = toml::from_str(&read_from_file_content)?;
println!("\nConfig read from file: {:#?}", config_from_file);
Ok(())
}








TOML