Skip to main content

trojan_config/
loader.rs

1//! Configuration file loading and error types.
2
3use std::{fs, path::Path};
4
5use crate::Config;
6
7#[derive(Debug, thiserror::Error)]
8pub enum ConfigError {
9    #[error("io: {0}")]
10    Io(#[from] std::io::Error),
11    #[error("json: {0}")]
12    Json(#[from] serde_json::Error),
13    #[error("yaml: {0}")]
14    Yaml(#[from] serde_yaml::Error),
15    #[error("toml: {0}")]
16    Toml(#[from] toml::de::Error),
17    #[error("unsupported config format")]
18    UnsupportedFormat,
19    #[error("validation: {0}")]
20    Validation(String),
21}
22
23pub fn load_config(path: impl AsRef<Path>) -> Result<Config, ConfigError> {
24    let path = path.as_ref();
25    let data = fs::read_to_string(path)
26        .map_err(|e| std::io::Error::new(e.kind(), format!("{}: {}", path.display(), e)))?;
27    match path.extension().and_then(|s| s.to_str()).unwrap_or("") {
28        "json" | "jsonc" => {
29            let stripped = json_comments::StripComments::new(data.as_bytes());
30            Ok(serde_json::from_reader(stripped)?)
31        }
32        "yaml" | "yml" => Ok(serde_yaml::from_str(&data)?),
33        "toml" => Ok(toml::from_str(&data)?),
34        _ => Err(ConfigError::UnsupportedFormat),
35    }
36}