br_db/
config.rs

1use json::{object, JsonValue};
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap;
4use std::fs;
5use std::path::PathBuf;
6
7#[derive(Clone, Debug, Deserialize, Serialize)]
8pub struct Config {
9    pub default: String,
10    pub connections: BTreeMap<String, Connection>,
11}
12
13impl Default for Config {
14    fn default() -> Self {
15        Self::new()
16    }
17}
18
19impl Config {
20    pub fn new() -> Config {
21        let mut connections = BTreeMap::new();
22        connections.insert("sqlite".to_string(), Connection::new("sqlite"));
23        connections.insert("mysql".to_string(), Connection::new("mysql"));
24        connections.insert("pgsql".to_string(), Connection::new("pgsql"));
25        connections.insert("mssql".to_string(), Connection::new("mssql"));
26        Self {
27            default: "sqlite".to_string(),
28            connections,
29        }
30    }
31    pub fn from(data: JsonValue) -> Config {
32        let default = data["default"].to_string();
33        let mut connections = BTreeMap::new();
34        for (key, value) in data["connections"].entries() {
35            let connection = Connection::from(value.clone()).clone();
36            connections.insert(key.to_string(), connection.clone());
37        }
38
39        Self {
40            default,
41            connections,
42        }
43    }
44    pub fn create(config_file: PathBuf, pkg_name: bool) -> Config {
45        #[derive(Clone, Debug, Deserialize, Serialize)]
46        pub struct ConfigPkg {
47            pub br_db: Config,
48        }
49        impl ConfigPkg {
50            pub fn new() -> ConfigPkg {
51                let mut connections = BTreeMap::new();
52                connections.insert("sqlite".to_string(), Connection::new("sqlite"));
53                connections.insert("mysql".to_string(), Connection::new("mysql"));
54                connections.insert("pgsql".to_string(), Connection::new("pgsql"));
55                connections.insert("mssql".to_string(), Connection::new("mssql"));
56                Self {
57                    br_db: Config {
58                        default: "sqlite".to_string(),
59                        connections,
60                    }
61                }
62            }
63        }
64        match fs::read_to_string(config_file.clone()) {
65            Ok(e) => {
66                if pkg_name {
67                    toml::from_str::<ConfigPkg>(&e).unwrap().br_db
68                } else {
69                    toml::from_str::<Config>(&e).unwrap()
70                }
71            }
72            Err(_) => {
73                if pkg_name {
74                    let data = ConfigPkg::new();
75                    fs::create_dir_all(config_file.parent().unwrap()).unwrap();
76                    let toml = toml::to_string(&data).unwrap();
77                    let _ = fs::write(config_file.to_str().unwrap(), toml);
78                    data.br_db
79                } else {
80                    let data = Config::new();
81                    fs::create_dir_all(config_file.parent().unwrap()).unwrap();
82                    let toml = toml::to_string(&data).unwrap();
83                    let _ = fs::write(config_file.to_str().unwrap(), toml);
84                    data
85                }
86            }
87        }
88    }
89    /// 设置新地连接配置
90    pub fn set_connection(&mut self, name: &str, connection: JsonValue) {
91        let connection = Connection::from(connection);
92        self.connections.insert(name.to_string(), connection);
93    }
94    /// 设置当前运行配置
95    pub fn set_default(&mut self, name: &str) {
96        self.default = name.to_string();
97    }
98}
99/// 数据库模式
100#[derive(Clone, Debug, Deserialize, Serialize)]
101pub enum Mode {
102    Mysql,
103    Mssql,
104    Sqlite,
105    Pgsql,
106    None,
107}
108
109impl Mode {
110    pub fn str(&mut self) -> String {
111        match self {
112            Mode::Mysql => "mysql",
113            Mode::Sqlite => "sqlite",
114            Mode::Mssql => "mssql",
115            Mode::Pgsql => "pgsql",
116            Mode::None => "",
117        }.to_string()
118    }
119    pub fn from(name: &str) -> Self {
120        match name.to_lowercase().as_str() {
121            "mysql" => Mode::Mysql,
122            "sqlite" => Mode::Sqlite,
123            "mssql" => Mode::Mssql,
124            "pgsql" => Mode::Pgsql,
125            _ => Mode::None,
126        }
127    }
128}
129
130
131/// 数据库连接
132#[derive(Clone, Debug, Deserialize, Serialize)]
133pub struct Connection {
134    pub mode: Mode,
135    /// 连接地址
136    pub hostname: String,
137    /// 连接端口
138    pub hostport: String,
139    /// 数据库名称
140    pub database: String,
141    /// 账号
142    pub username: String,
143    /// 密码
144    pub userpass: String,
145    pub params: Vec<String>,
146    /// 数据库语言
147    pub charset: Charset,
148    /// 表前缀
149    pub prefix: String,
150    /// 调试开关
151    pub debug: bool,
152}
153
154impl Default for Connection {
155    fn default() -> Self {
156        Self::new("sqlite")
157    }
158}
159
160impl Connection {
161    pub fn new(mode: &str) -> Connection {
162        let mut that = Self {
163            mode: Mode::from(mode),
164            hostname: "".to_string(),
165            hostport: "".to_string(),
166            database: "".to_string(),
167            username: "".to_string(),
168            userpass: "".to_string(),
169            params: vec![],
170            charset: Charset::Utf8mb4,
171            prefix: "".to_string(),
172            debug: false,
173        };
174        match Mode::from(mode) {
175            Mode::Mysql => {
176                that.hostname = "127.0.0.1".to_string();
177                that.hostport = "3306".to_string();
178                that.database = "test".to_string();
179                that.username = "test".to_string();
180                that.userpass = "test".to_string();
181            }
182            Mode::Mssql => {}
183            Mode::Sqlite => {
184                that.database = "db/app.db".to_string();
185            }
186            Mode::Pgsql => {
187                that.hostname = "127.0.0.1".to_string();
188                that.hostport = "5432".to_string();
189                that.username = "test".to_string();
190                that.userpass = "test".to_string();
191            }
192            Mode::None => {}
193        }
194
195        that
196    }
197    pub fn json(&mut self) -> JsonValue {
198        object! {
199            mode: self.mode.str(),
200            hostname: self.hostname.clone(),
201            hostport: self.hostport.clone(),
202            database: self.database.clone(),
203            username: self.username.clone(),
204            userpass:self.userpass.clone(),
205            params: self.params.clone(),
206            charset: self.charset.str(),
207            prefix: self.prefix.clone(),
208            debug: self.debug
209        }
210    }
211    pub fn from(data: JsonValue) -> Connection {
212        Self {
213            mode: Mode::from(data["mode"].as_str().unwrap()),
214            hostname: data["hostname"].to_string(),
215            hostport: data["hostport"].to_string(),
216            database: data["database"].to_string(),
217            username: data["username"].to_string(),
218            userpass: data["userpass"].to_string(),
219            params: data["params"].members().map(|x| x.to_string()).collect(),
220            charset: Charset::from(data["charset"].as_str().unwrap_or("utf8mb4")),
221            prefix: data["prefix"].as_str().unwrap_or("").to_string(),
222            debug: data["debug"].to_string().parse::<bool>().unwrap_or(false),
223        }
224    }
225    pub fn get_dsn(self) -> String {
226        match self.mode {
227            Mode::Mysql => {
228                format!(
229                    "mysql://{}:{}@{}:{}/{}",
230                    self.username, self.userpass, self.hostname, self.hostport, self.database
231                )
232            }
233            Mode::Sqlite => {
234                let db_path = self.database.as_str();
235                let path_buf = PathBuf::from(db_path);
236                if !path_buf.is_file() && path_buf.file_name().is_some() {
237                    fs::create_dir_all(
238                        db_path.trim_end_matches(path_buf.file_name().unwrap().to_str().unwrap()),
239                    ).unwrap();
240                }
241                path_buf.to_str().unwrap().to_string()
242            }
243            Mode::Mssql => format!(
244                "sqlsrv://{}:{}@{}:{}/{}",
245                self.username, self.userpass, self.hostname, self.hostport, self.database
246            ),
247            Mode::Pgsql => format!(
248                "host={} user={} password={} dbname={}",
249                self.hostname, self.username, self.userpass, self.database
250            ),
251            Mode::None => "".to_string(),
252        }
253    }
254}
255
256#[derive(Clone, Debug, Deserialize, Serialize)]
257pub enum Charset {
258    Utf8mb4,
259    Utf8,
260    None,
261}
262
263impl Charset {
264    pub fn from(str: &str) -> Charset {
265        match str.to_lowercase().as_str() {
266            "utf8" => Charset::Utf8,
267            "utf8mb4" => Charset::Utf8mb4,
268            _ => Charset::None,
269        }
270    }
271    pub fn str(&self) -> String {
272        match self {
273            Charset::Utf8 => "utf8",
274            Charset::Utf8mb4 => "utf8mb4",
275            Charset::None => "",
276        }.to_string()
277    }
278}