fkl_parser/mir/implementation/
datasource.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4pub enum Datasource {
5 MySql(MySqlDatasource),
6 Postgres(PostgresDatasource),
7}
8
9impl Datasource {
10 pub fn from(url: &str) -> Result<Datasource, String> {
11 let url = url::Url::parse(url).map_err(|e| e.to_string())?;
12 let scheme = url.scheme();
13 let host = url.host_str().ok_or("host is required")?.to_string();
14 let port = url.port().ok_or("port is required")?;
15 let username = url.username().to_string();
16 let password = url.password().unwrap_or("").to_string();
17 let database = url.path().trim_start_matches('/').to_string();
18
19 match scheme {
20 "mysql" => Ok(Datasource::MySql(MySqlDatasource {
21 host,
22 port,
23 username,
24 password,
25 database,
26 })),
27 "postgresql" => Ok(Datasource::Postgres(PostgresDatasource {
28 host,
29 port,
30 username,
31 password,
32 database,
33 })),
34 _ => Err(format!("unsupported scheme: {}", scheme)),
35 }
36 }
37
38 #[allow(dead_code)]
39 fn url(&self) -> String {
40 match self {
41 Datasource::MySql(config) => MySqlDatasource::url(config),
42 Datasource::Postgres(config) => format!(
43 "postgresql://{}:{}@{}:{}/{}",
44 config.username, config.password, config.host, config.port, config.database
45 ),
46 }
47 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
51pub struct MySqlDatasource {
52 pub host: String,
53 pub port: u16,
54 pub username: String,
55 pub password: String,
56 pub database: String,
57}
58
59impl MySqlDatasource {
60 pub fn url(&self) -> String {
61 format!(
62 "mysql://{}:{}@{}:{}/{}",
63 self.username, self.password, self.host, self.port, self.database
64 )
65 }
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
69pub struct PostgresDatasource {
70 pub host: String,
71 pub port: u16,
72 pub username: String,
73 pub password: String,
74 pub database: String,
75}
76
77impl PostgresDatasource {
78 pub fn url(&self) -> String {
79 format!(
80 "postgresql://{}:{}@{}:{}/{}",
81 self.username, self.password, self.host, self.port, self.database
82 )
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_parse_database_url() {
92 let url = "mysql://username:password@localhost:3306/database";
93 let datasource = Datasource::from(url).unwrap();
94 assert_eq!(
95 datasource,
96 Datasource::MySql(MySqlDatasource {
97 host: "localhost".to_string(),
98 port: 3306,
99 username: "username".to_string(),
100 password: "password".to_string(),
101 database: "database".to_string(),
102 })
103 );
104 }
105
106 #[test]
107 fn test_parse_normal_postgres() {
108 let url = "postgresql://localhost:5432/yourdb";
109 let datasource = Datasource::from(url).unwrap();
110
111 assert_eq!(
112 datasource,
113 Datasource::Postgres(PostgresDatasource {
114 host: "localhost".to_string(),
115 port: 5432,
116 username: "".to_string(),
117 password: "".to_string(),
118 database: "yourdb".to_string(),
119 })
120 );
121 }
122
123 #[test]
124 fn test_mysql_url_gen() {
125 let datasource = Datasource::MySql(MySqlDatasource {
126 host: "localhost".to_string(),
127 port: 3306,
128 username: "username".to_string(),
129 password: "password".to_string(),
130 database: "database".to_string(),
131 });
132 assert_eq!(datasource.url(),
133 "mysql://username:password@localhost:3306/database"
134 );
135 }
136}