تمرين إعادة البناء
Config Loader
أعد كتابة قارئ إعدادات key=value مع قيم افتراضية وتحقق بسيط.
rust
~20 دقيقة
متوسط
أعد بناء الكود
Rebuild
هذا هو الكود. اكتبه بنفسك.
الكود المرجعي
use std::collections::BTreeMap;
use std::env;
use std::fs;
use std::io;
#[derive(Debug)]
struct Config {
host: String,
port: u16,
debug: bool,
}
fn main() -> io::Result<()> {
let path = env::args()
.nth(1)
.unwrap_or_else(|| "app.conf".to_string());
let text = fs::read_to_string(path).unwrap_or_else(|_| sample_config());
let values = parse_key_values(&text);
let config = Config::from_values(&values);
println!("host={}", config.host);
println!("port={}", config.port);
println!("debug={}", config.debug);
Ok(())
}
impl Config {
fn from_values(values: &BTreeMap<String, String>) -> Self {
Self {
host: values
.get("host")
.cloned()
.unwrap_or_else(|| "127.0.0.1".to_string()),
port: values
.get("port")
.and_then(|value| value.parse().ok())
.filter(|port| *port > 0)
.unwrap_or(8080),
debug: values
.get("debug")
.map(|value| matches!(value.as_str(), "true" | "1" | "yes"))
.unwrap_or(false),
}
}
}
fn parse_key_values(text: &str) -> BTreeMap<String, String> {
let mut values = BTreeMap::new();
for line in text.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
if let Some((key, value)) = line.split_once('=') {
values.insert(key.trim().to_string(), value.trim().to_string());
}
}
values
}
fn sample_config() -> String {
"host=0.0.0.0\nport=3000\ndebug=true\n".to_string()
}اكتب هنا