ricecoder_lsp/config/
loader.rs1use super::types::{ConfigError, ConfigRegistry, ConfigResult, LanguageConfig};
4use std::path::Path;
5
6pub struct ConfigLoader;
8
9impl ConfigLoader {
10 pub fn load_yaml(path: &Path) -> ConfigResult<LanguageConfig> {
12 let content = std::fs::read_to_string(path)?;
13 let config: LanguageConfig = serde_yaml::from_str(&content)?;
14 config.validate()?;
15 Ok(config)
16 }
17
18 pub fn load_json(path: &Path) -> ConfigResult<LanguageConfig> {
20 let content = std::fs::read_to_string(path)?;
21 let config: LanguageConfig = serde_json::from_str(&content)?;
22 config.validate()?;
23 Ok(config)
24 }
25
26 pub fn load(path: &Path) -> ConfigResult<LanguageConfig> {
28 match path.extension().and_then(|ext| ext.to_str()) {
29 Some("yaml") | Some("yml") => Self::load_yaml(path),
30 Some("json") => Self::load_json(path),
31 _ => Err(ConfigError::ValidationError(
32 "Unsupported configuration file format".to_string(),
33 )),
34 }
35 }
36
37 pub fn load_directory(path: &Path) -> ConfigResult<ConfigRegistry> {
39 let mut registry = ConfigRegistry::new();
40
41 if !path.is_dir() {
42 return Err(ConfigError::ValidationError(format!(
43 "Path is not a directory: {}",
44 path.display()
45 )));
46 }
47
48 for entry in std::fs::read_dir(path)? {
49 let entry = entry?;
50 let path = entry.path();
51
52 if path.is_file() {
53 if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
54 if ext == "yaml" || ext == "yml" || ext == "json" {
55 match Self::load(&path) {
56 Ok(config) => {
57 registry.register(config)?;
58 }
59 Err(e) => {
60 tracing::warn!(
61 "Failed to load configuration from {}: {}",
62 path.display(),
63 e
64 );
65 }
66 }
67 }
68 }
69 }
70 }
71
72 Ok(registry)
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_load_unsupported_format() {
82 let result = ConfigLoader::load(Path::new("test.txt"));
83 assert!(result.is_err());
84 }
85}