Introduction au travail avec YAML en Rust
YAML (YAML Ain't Markup Language) est l'un des formats les plus populaires pour les fichiers de configuration grâce à sa lisibilité et sa flexibilité. Dans l'écosystème Rust, la crate serde_yaml est utilisée pour travailler avec YAML, construite sur la puissante plateforme de sérialisation Serde. Cette bibliothèque permet de convertir facilement les structures Rust en YAML et vice versa.
Installation et configuration
Ajoutez les dépendances à votre Cargo.toml :
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_yaml = "0.9"Après avoir mis à jour le projet, exécutez cargo build. La bibliothèque est prête à être utilisée.
Désérialisation de base de YAML en Rust
Considérons un exemple simple : lire une chaîne YAML et la convertir en une structure Rust.
Étape 1 : Définir la structure
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct Config { host: String, port: u16, debug: bool,}Étape 2 : Analyser le YAML
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(())}Sortie : Config { host: "127.0.0.1", port: 8080, debug: true }
Sérialisation de structures Rust en YAML
Le processus inverse : convertir des données Rust en une chaîne YAML :
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(())}Résultat :
---name: web-serverip: 10.0.0.1ports: - 80 - 443 - 22Travailler avec des structures imbriquées et des balises
YAML prend en charge les hiérarchies complexes. En Rust, cela se traduit par des structures imbriquées et des énumérations :
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(())}Notez l'attribut #[serde(rename = "db")] — il permet de faire correspondre un champ Rust avec un autre nom en YAML.
Gestion des erreurs et des champs optionnels
Les fichiers YAML réels contiennent souvent des paramètres optionnels. Utilisez 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}L'attribut #[serde(default)] attribue une valeur par défaut (vecteur vide pour Vec, None pour Option). Vous pouvez spécifier une fonction génératrice, comme dans l'exemple avec timeout.
Lecture de YAML à partir d'un fichier
En pratique, les configurations sont stockées dans des fichiers. La lecture est simple :
use std::fs;use serde_yaml;
fn main() -> Result<(), Box<dyn std::error::Error>