winbrew_database\config/
validation.rs1use super::error::{ConfigError, ConfigResult};
2
3use super::{registry, types::Config};
4
5impl Config {
6 pub fn set_value(&mut self, key: &str, value: &str) -> ConfigResult<()> {
7 let key = key.trim();
8
9 if key.is_empty() {
10 return Err(ConfigError::EmptyKey);
11 }
12
13 let value = value.trim();
14 validate_config_value(key, value)?;
15 let value = value.to_string();
16
17 match key {
18 "core.log_level" => self.core.log_level = value,
19 "core.file_log_level" => self.core.file_log_level = value,
20 "core.auto_update" => self.core.auto_update = parse_bool(key, &value)?,
21 "core.confirm_remove" => self.core.confirm_remove = parse_bool(key, &value)?,
22 "core.default_yes" => self.core.default_yes = parse_bool(key, &value)?,
23 "core.color" => self.core.color = parse_bool(key, &value)?,
24 "paths.root" => self.paths.root = value,
25 "paths.packages" => self.paths.packages = value,
26 "paths.data" => self.paths.data = value,
27 "paths.logs" => self.paths.logs = value,
28 "paths.cache" => self.paths.cache = value,
29 _ => {
30 return Err(ConfigError::UnknownKey {
31 key: key.to_string(),
32 });
33 }
34 }
35
36 Ok(())
37 }
38
39 pub fn unset_value(&mut self, key: &str) -> ConfigResult<()> {
40 let key = key.trim();
41
42 if key.is_empty() {
43 return Err(ConfigError::EmptyKey);
44 }
45
46 ensure_known_key(key)?;
47
48 let defaults = Config::default();
49
50 match key {
51 "core.log_level" => self.core.log_level = defaults.core.log_level,
52 "core.file_log_level" => self.core.file_log_level = defaults.core.file_log_level,
53 "core.auto_update" => self.core.auto_update = defaults.core.auto_update,
54 "core.confirm_remove" => self.core.confirm_remove = defaults.core.confirm_remove,
55 "core.default_yes" => self.core.default_yes = defaults.core.default_yes,
56 "core.color" => self.core.color = defaults.core.color,
57 "paths.root" => self.paths.root = defaults.paths.root,
58 "paths.packages" => self.paths.packages = defaults.paths.packages,
59 "paths.data" => self.paths.data = defaults.paths.data,
60 "paths.logs" => self.paths.logs = defaults.paths.logs,
61 "paths.cache" => self.paths.cache = defaults.paths.cache,
62 _ => {
63 return Err(ConfigError::UnknownKey {
64 key: key.to_string(),
65 });
66 }
67 }
68
69 Ok(())
70 }
71}
72
73fn parse_bool(key: &str, value: &str) -> ConfigResult<bool> {
74 registry::parse_bool_value(value).ok_or_else(|| ConfigError::InvalidValue {
75 key: key.to_string(),
76 value: value.to_string(),
77 })
78}
79
80fn validate_config_value(key: &str, value: &str) -> ConfigResult<()> {
81 let def = ensure_known_key(key)?;
82
83 if let Some(validator) = def.validator {
84 validator(value).map_err(|source| ConfigError::Validation {
85 key: key.to_string(),
86 source,
87 })?;
88 }
89
90 Ok(())
91}
92
93fn ensure_known_key(key: &str) -> ConfigResult<&'static registry::KeyDef> {
94 registry::find(key).ok_or_else(|| ConfigError::UnknownKey {
95 key: key.to_string(),
96 })
97}
98
99#[cfg(test)]
100mod tests {
101 use super::{Config, ConfigError};
102
103 #[test]
104 fn set_value_accepts_boolean_aliases_in_validation() {
105 let mut config = Config::default();
106
107 config.set_value("core.auto_update", "yes").unwrap();
108 config.set_value("core.confirm_remove", "on").unwrap();
109 config.set_value("core.default_yes", "1").unwrap();
110
111 assert!(config.core.auto_update);
112 assert!(config.core.confirm_remove);
113 assert!(config.core.default_yes);
114 }
115
116 #[test]
117 fn set_value_accepts_env_filter_syntax_for_console_log_level() {
118 let mut config = Config::default();
119
120 config
121 .set_value("core.log_level", "winbrew=debug,info")
122 .unwrap();
123
124 assert_eq!(config.core.log_level, "winbrew=debug,info");
125 }
126
127 #[test]
128 fn unset_value_restores_default_values() {
129 let mut config = Config::default();
130
131 config.set_value("core.auto_update", "false").unwrap();
132 config.set_value("paths.packages", "C:\\custom").unwrap();
133
134 config.unset_value("core.auto_update").unwrap();
135 config.unset_value("paths.packages").unwrap();
136
137 let defaults = Config::default();
138
139 assert_eq!(config.core.auto_update, defaults.core.auto_update);
140 assert_eq!(config.paths.packages, defaults.paths.packages);
141 }
142
143 #[test]
144 fn unset_value_rejects_unknown_keys() {
145 let mut config = Config::default();
146
147 let err = config.unset_value("core.proxy").unwrap_err();
148
149 assert!(matches!(err, ConfigError::UnknownKey { .. }));
150 }
151}