العمل مع YAML في Rust: مكتبة serde_yaml

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مكتبة serde_yaml: العمل مع YAML في Rust

YAML (YAML Ain't Markup Language) هو أحد أشهر صيغ تسلسل البيانات، ويُستخدم على نطاق واسع في ملفات الإعدادات ووصف هياكل البيانات وتبادل المعلومات بين الخدمات. في نظام Rust البيئي، توجد مكتبة ناضجة وعالية الأداء تُسمى serde_yaml، المبنية على إطار العمل القوي serde للتسلسل. في هذا المقال، سنشرح بالتفصيل كيفية تحليل وإنشاء ومعالجة مستندات YAML في Rust.

التثبيت والإعداد

للبدء، أضف التبعيات التالية إلى ملف Cargo.toml الخاص بك:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"

ستقوم مكتبة serde_yaml تلقائياً بجلب جميع المكونات اللازمة لتحليل وإنشاء YAML.

إلغاء التسلسل الأساسي (YAML → هيكل Rust)

السيناريو الأكثر شيوعاً هو قراءة ملف إعدادات. دعنا نعرف هيكلاً يطابق مستند 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,
}

الآن، لنقرأ ملف YAML ونحوله إلى هيكل:

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!("الخادم: {}:{}", config.server.host, config.server.port);
    println!("قاعدة البيانات: {}", config.database.url);
    
    Ok(())
}

مثال لملف config.yaml:

server:
  host: "127.0.0.1"
  port: 8080
  workers: 4
database:
  url: "postgres://user:pass@localhost/db"
  pool_size: 10

التسلسل (هيكل Rust → YAML)

العملية العكسية هي إنشاء مستند YAML من البيانات الموجودة في الذاكرة:

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);
    
    // حفظ في ملف
    std::fs::write("project.yaml", &yaml_string)?;
    
    Ok(())
}

التعامل مع مستندات YAML غير المعروفة الهيكل

أحياناً يكون هيكل YAML غير معروف مسبقاً. في هذه الحالات، استخدم serde_yaml::Value:

use serde_yaml::Value;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let yaml_data = "
apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app: web
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app: web
";
    
    let value: Value = serde_yaml::from_str(yaml_data)?;
    
    // الوصول إلى البيانات المتداخلة
    if let Some(ports) = value["spec"]["ports"].as_sequence() {
        for port in ports {
            if let Some(port_num) = port["port"].as_u64() {
                println!("المنفذ: {}", port_num);
            }
        }
    }
    
    // تعديل                    

توصيات