Einführung in die Arbeit mit YAML in Rust
YAML (YAML Ain't Markup Language) ist eines der beliebtesten Formate für Konfigurationsdateien aufgrund seiner Lesbarkeit und Flexibilität. Im Rust-Ökosystem wird für die Arbeit mit YAML die Crate serde_yaml verwendet, die auf der leistungsstarken Serialisierungsplattform Serde aufbaut. Diese Bibliothek ermöglicht es, Rust-Strukturen einfach in YAML und zurück zu konvertieren.
Installation und Einrichtung
Fügen Sie die Abhängigkeiten zu Ihrer Cargo.toml hinzu:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_yaml = "0.9"Führen Sie nach der Aktualisierung des Projekts cargo build aus. Die Bibliothek ist bereit zur Verwendung.
Basis-Deserialisierung von YAML in Rust
Betrachten wir ein einfaches Beispiel – das Einlesen eines YAML-Strings und dessen Umwandlung in eine Rust-Struktur.
Schritt 1: Struktur definieren
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct Config { host: String, port: u16, debug: bool,}Schritt 2: YAML parsen
use serde_yaml;
fn main() -> Result<(), serde_yaml::Error> { let yaml_str = r#" host: "127.0.0.1" port: 8080 debug: true "#;
let config: Config = serde_yaml::from_str(yaml_str)?; println!("{:?}", config); Ok(())}Ausgabe: Config { host: "127.0.0.1", port: 8080, debug: true }
Serialisierung von Rust-Strukturen in YAML
Der umgekehrte Prozess – die Umwandlung von Rust-Daten in einen YAML-String:
use serde::Serialize;
#[derive(Debug, Serialize)]struct Server { name: String, ip: String, ports: Vec<u16>,}
fn main() -> Result<(), serde_yaml::Error> { let server = Server { name: "web-server".into(), ip: "10.0.0.1".into(), ports: vec![80, 443, 22], };
let yaml = serde_yaml::to_string(&server)?; println!("{}", yaml); Ok(())}Ergebnis:
---name: web-serverip: 10.0.0.1ports: - 80 - 443 - 22Arbeiten mit verschachtelten Strukturen und Tags
YAML unterstützt komplexe Hierarchien. In Rust wird dies durch verschachtelte Strukturen und Enums abgebildet:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]struct Database { #[serde(rename = "db")] database: DbConfig, pool_size: u32,}
#[derive(Debug, Serialize, Deserialize)]struct DbConfig { host: String, port: u16, user: String, password: String,}
fn main() -> Result<(), serde_yaml::Error> { let yaml = r#" db: host: "localhost" port: 5432 user: "admin" password: "secret" pool_size: 10 "#;
let db: Database = serde_yaml::from_str(yaml)?; println!("{:#?}", db); Ok(())}Beachten Sie das Attribut #[serde(rename = "db")] – es ermöglicht, ein Rust-Feld einem anderen Namen in YAML zuzuordnen.
Fehlerbehandlung und optionale Felder
Reale YAML-Dateien enthalten oft optionale Parameter. Verwenden Sie Option<T>:
#[derive(Debug, Deserialize)]struct AppConfig { name: String, version: String, #[serde(default)] features: Vec<String>, #[serde(default = "default_timeout")] timeout: u64,}
fn default_timeout() -> u64 { 30}Das Attribut #[serde(default)] weist einen Standardwert zu (leerer Vektor für Vec, None für Option). Sie können eine Generatorfunktion angeben, wie im Beispiel mit timeout.
YAML aus einer Datei lesen
In der Praxis werden Konfigurationen in Dateien gespeichert. Das Einlesen erfolgt einfach:
use std::fs;use serde_yaml;
fn main() -> Result<(), Box<dyn std::error::Error>