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 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 pub fn set_default(&mut self, name: &str) {
96 self.default = name.to_string();
97 }
98}
99#[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#[derive(Clone, Debug, Deserialize, Serialize)]
133pub struct Connection {
134 pub mode: Mode,
135 pub hostname: String,
137 pub hostport: String,
139 pub database: String,
141 pub username: String,
143 pub userpass: String,
145 pub params: Vec<String>,
146 pub charset: Charset,
148 pub prefix: String,
150 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}