rest_api/
config_parser.rs

1use std::collections::HashMap;
2use std::fs::File;
3use std::io::Read;
4use std::path::Path;
5
6use super::database::table_schema::SqlTableSchema;
7use super::database::interfaces::SQLType;
8
9use toml::Value;
10
11const DEFAULT_CONFIG_PATH: &str = "server_config.toml";
12
13pub fn read_config(optional_path: Option<&str>) -> (HashMap<String, String>, HashMap<String, SqlTableSchema>) {
14    // will panic with error message if config file can't be read, as this is unrecoverable
15    // return general config HashMap<String, String>
16    // and HashMap {route string: table_schema}
17
18    let config_path = Path::new(
19        match optional_path {
20            Some(p) => p,
21            None => DEFAULT_CONFIG_PATH
22        }
23    );
24
25    let mut buffer = Vec::new();
26    let _res = File::open(config_path).expect("Can't open config file").read_to_end(&mut buffer);
27
28    let file_string = String::from_utf8(buffer).expect("Can't construct string from bytes in config file");
29    let mut toml_parsed = file_string.parse::<Value>().expect("Can't pass toml config");
30
31    let toml_main_table = toml_parsed.as_table_mut().expect("Toml config couldn't be parsed as table");
32    let mut table_data = toml_main_table
33        .remove("table")
34        .expect("No tables found in config");
35
36    let table_data = table_data
37        .as_table_mut()
38        .expect("Tables in config aren't of toml 'Table' type");
39
40    let mut general_config = HashMap::new();
41    for config in toml_main_table {
42        let value = config.1.as_str();
43        if value.is_none() {
44            panic!("Encountered non-string value in toml config")
45        }
46
47        general_config.insert(config.0.clone(), value.unwrap().to_string());
48    }
49
50    let mut table_routes = HashMap::new();
51    for table in table_data {
52        let table_name = table.0;
53
54        let table_attributes = table.1.as_table_mut().expect("Contents of table aren't of toml 'Table' type");
55
56        let route = table_attributes.remove("route")
57            .expect("Table has no 'route'");
58
59        let route = route
60            .as_str()
61            .expect("Route value isn't 'String'");
62
63        let mut table_schema_mapping = HashMap::new();
64        
65        for field in table_attributes {
66            let sql_type_string = field.1.as_str().expect("Encountered non-string SQL type value").to_ascii_lowercase();
67            let field_sql_type = match sql_type_string.as_str() {
68                "null" => Some(SQLType::Null),
69                "real" => Some(SQLType::Real),
70                "integer" => Some(SQLType::Integer),
71                "text" => Some(SQLType::Text),
72                _ => None
73            };
74            if field_sql_type.is_none() {
75                panic!("Invalid SQL type found in table field: {}", sql_type_string);
76            }
77            table_schema_mapping.insert(field.0.to_ascii_lowercase().clone(), field_sql_type.unwrap());
78        }
79
80        table_routes.insert(route.to_string(), SqlTableSchema {name: table_name.clone(), fields: table_schema_mapping});
81    }
82
83    (general_config, table_routes)
84}