مقدمة في العمل مع YAML على Rust
YAML (YAML Ain't Markup Language) — أحد أكثر التنسيقات شيوعًا لملفات الإعدادات بفضل سهولة قراءته ومرونته. في نظام Rust البيئي، يُستخدم الكريت serde_yaml للعمل مع YAML، وهو مبني على منصة التسلسل القوية Serde. تتيح هذه المكتبة تحويل هياكل Rust إلى YAML والعكس بسهولة.
التثبيت والإعداد
أضف التبعيات إلى ملف Cargo.toml الخاص بك:
[dependencies]serde = { version = "1.0", features = ["derive"] }serde_yaml = "0.9"بعد تحديث المشروع، نفّذ cargo build. المكتبة جاهزة للاستخدام.
إلغاء التسلسل الأساسي لـ YAML في Rust
لننظر إلى مثال بسيط — قراءة سلسلة YAML وتحويلها إلى هيكل Rust.
الخطوة 1: تعريف الهيكل
use serde::Deserialize;
#[derive(Debug, Deserialize)]struct Config { host: String, port: u16, debug: bool,}الخطوة 2: تحليل 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(())}المخرجات: Config { host: "127.0.0.1", port: 8080, debug: true }
تسلسل هياكل Rust إلى YAML
العملية العكسية — تحويل بيانات Rust إلى سلسلة 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(())}النتيجة:
---name: web-serverip: 10.0.0.1ports: - 80 - 443 - 22العمل مع الهياكل المتداخلة والوسوم
يدعم YAML التسلسلات الهرمية المعقدة. في Rust، يُعكس ذلك على هياكل وتعدادات متداخلة:
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(())}لاحظ السمة #[serde(rename = "db")] — فهي تسمح بمطابقة حقل Rust مع اسم آخر في YAML.
معالجة الأخطاء والحقول الاختيارية
غالبًا ما تحتوي ملفات YAML الحقيقية على معاملات اختيارية. استخدم 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}السمة #[serde(default)] تُعيّن قيمة افتراضية (مصفوفة فارغة لـ Vec، None لـ Option). يمكن تحديد دالة مولّدة، كما في مثال timeout.
قراءة YAML من ملف
عمليًا، تُخزّن الإعدادات في ملفات. القراءة بسيطة:
use std::fs;use serde_yaml;
fn main() -> Result<(), Box<dyn std::error::Error>