Biblioteca serde_yaml: trabalhando com YAML em Rust
YAML (YAML Ain't Markup Language) é um dos formatos de serialização de dados mais populares, amplamente utilizado para arquivos de configuração, descrição de estruturas de dados e troca de informações entre serviços. No ecossistema Rust, existe uma biblioteca madura e performática chamada serde_yaml para trabalhar com YAML, construída sobre o poderoso framework de serialização serde. Neste artigo, vamos detalhar como analisar, criar e processar documentos YAML em Rust.
Instalação e configuração
Para começar, adicione as seguintes dependências ao seu Cargo.toml:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_yaml = "0.9"A biblioteca serde_yaml puxará automaticamente todos os componentes necessários para análise e geração de YAML.
Desserialização básica (YAML → estrutura Rust)
O cenário mais comum é a leitura de um arquivo de configuração. Vamos definir uma estrutura que corresponde ao documento YAML:
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct Config { server: ServerConfig, database: DatabaseConfig,}
#[derive(Debug, Deserialize)]struct ServerConfig { host: String, port: u16, workers: Option<u32>,}
#[derive(Debug, Deserialize)]struct DatabaseConfig { url: String, pool_size: u32,}Agora, vamos ler o arquivo YAML e convertê-lo para a estrutura:
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> { let yaml_content = fs::read_to_string("config.yaml")?; let config: Config = serde_yaml::from_str(&yaml_content)?; println!("Servidor: {}:{}", config.server.host, config.server.port); println!("Banco de dados: {}", config.database.url); Ok(())}Exemplo do arquivo config.yaml:
server: host: "127.0.0.1" port: 8080 workers: 4database: url: "postgres://user:pass@localhost/db" pool_size: 10Serialização (estrutura Rust → YAML)
O processo inverso — criar um documento YAML a partir de dados em memória:
use serde::Serialize;
#[derive(Debug, Serialize)]struct Project { name: String, version: String, dependencies: Vec<Dependency>,}
#[derive(Debug, Serialize)]struct Dependency { name: String, version: String, optional: bool,}
fn main() -> Result<(), Box<dyn std::error::Error>> { let project = Project { name: "my-app".to_string(), version: "0.1.0".to_string(), dependencies: vec![ Dependency { name: "serde".to_string(), version: "1.0".to_string(), optional: false, }, Dependency { name: "tokio".to_string(), version: "1.35".to_string(), optional: true, }, ], };
let yaml_string = serde_yaml::to_string(&project)?; println!("{}", yaml_string); // Salva no arquivo std::fs::write("project.yaml", &yaml_string)?; Ok(())}Trabalhando com documentos YAML arbitrários
Às vezes, a estrutura do YAML não é conhecida antecipadamente. Nesses casos, use serde_yaml::Value:
use serde_yaml::Value;
fn main() -> Result<(), Box<dyn std::error::Error>> { let yaml_data = "apiVersion: v1kind: Servicemetadata: name: my-service labels: app: webspec: ports: - port: 80 targetPort: 8080 selector: app: web"; let value: Value = serde_yaml::from_str(yaml_data)?; // Acesso a dados aninhados if let Some(ports) = value["spec"]["ports"].as_sequence() { for port in ports { if let Some(port_num