fkl_parser/mir/implementation/
datasource.rs

1use 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}