1use 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}