1use std::collections::HashMap;
6use std::path::Path;
7
8use serde::Deserialize;
9
10pub trait IntoMysqlName {
12 fn into_name(self) -> String;
13}
14
15pub trait IntoRedisName {
17 fn into_name(self) -> String;
18}
19
20impl IntoMysqlName for String {
22 fn into_name(self) -> String {
23 self
24 }
25}
26
27impl IntoMysqlName for &str {
29 fn into_name(self) -> String {
30 self.to_string()
31 }
32}
33
34impl IntoRedisName for String {
36 fn into_name(self) -> String {
37 self
38 }
39}
40
41impl IntoRedisName for &str {
43 fn into_name(self) -> String {
44 self.to_string()
45 }
46}
47
48#[derive(Debug, Clone, Deserialize)]
50pub struct MysqlConfig {
51 pub host: String,
53 #[serde(default = "default_mysql_port")]
55 pub port: u16,
56 #[serde(alias = "username")]
58 pub user: String,
59 pub password: String,
61 #[serde(default)]
63 pub database: String,
64 #[serde(default = "default_max_connections")]
66 pub max_connections: u32,
67 #[serde(default = "default_ssl_mode")]
69 pub ssl_mode: String,
70}
71
72fn default_mysql_port() -> u16 {
73 3306
74}
75fn default_max_connections() -> u32 {
76 5
77}
78fn default_ssl_mode() -> String {
79 "preferred".to_string()
80}
81
82#[derive(Debug, Clone, Deserialize)]
84pub struct RedisConfig {
85 pub url: String,
87}
88
89#[derive(Debug, Clone, Default, Deserialize)]
91pub struct Config {
92 #[serde(default)]
94 pub mysql: HashMap<String, MysqlConfig>,
95 #[serde(default)]
97 pub redis: HashMap<String, RedisConfig>,
98}
99
100impl Config {
101 pub fn load<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
103 let path = path.as_ref();
104 let text = std::fs::read_to_string(path)
105 .map_err(|e| anyhow::anyhow!("读取配置文件 {} 失败: {}", path.display(), e))?;
106 let cfg: Config = toml::from_str(&text)
107 .map_err(|e| anyhow::anyhow!("解析配置文件 {} 失败: {}", path.display(), e))?;
108 Ok(cfg)
109 }
110
111 pub fn mysql(&self, name: &str) -> Option<&MysqlConfig> {
113 self.mysql.get(name)
114 }
115
116 pub fn redis(&self, name: &str) -> Option<&RedisConfig> {
118 self.redis.get(name)
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn parses_config() {
128 let toml = r#"
129 [mysql.default]
130 host = "h1"
131 port = 3306
132 user = "u1"
133 password = "p1"
134 database = "db1"
135 max_connections = 1
136 ssl_mode = "preferred"
137
138 [redis.default]
139 url = "redis://127.0.0.1:6379"
140 "#;
141 let cfg: Config = toml::from_str(toml).unwrap();
142
143 let d = cfg.mysql("default").unwrap();
144 assert_eq!(d.host, "h1");
145 assert_eq!(d.port, 3306);
146
147 assert_eq!(cfg.redis("default").unwrap().url, "redis://127.0.0.1:6379");
148 }
149}