msg_store_server_api/
lib.rs

1use msg_store_database_plugin::Db;
2pub mod export;
3pub mod file_storage;
4pub mod group;
5pub mod group_defaults;
6pub mod msg;
7pub mod stats;
8pub mod store;
9
10pub type Database = Box<dyn Db>;
11pub enum Either<A, B> {
12    A(A),
13    B(B)
14}
15impl<A, B> Either<A, B> {
16    pub fn a(self) -> A {
17        match self {
18            Self::A(inner) => inner,
19            Self::B(_) => panic!("Item is not A")
20        }
21    }
22    pub fn b(self) -> B {
23        match self {
24            Self::A(_) => panic!("Item is not B"),
25            Self::B(inner) => inner
26        }
27    }
28}
29
30pub mod config {
31    use serde::{Deserialize, Serialize};
32    use serde_json::{from_str as from_json_str, to_string_pretty as to_json_string};
33    use std::fmt::Display;
34    use std::fs::{self, read_to_string};
35    use std::path::{Path, PathBuf};
36
37#[derive(Debug)]
38pub enum ConfigErrorTy {
39    CouldNotConvertToJson,
40    CouldNotParseJson,
41    CouldNotReadFile,
42    CouldNotWriteToFile
43}
44impl Display for ConfigErrorTy {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        match self {
47            // Self::CouldNotCreateDirectory |
48            // Self::CouldNotCreateFile |
49            // Self::CouldNotGetChunkFromPayload |
50            // Self::CouldNotReadDirectory |
51            // Self::CouldNotReadMetadata |
52            // Self::CouldNotRemoveFile |
53            // Self::CouldNotOpenFile |
54            Self::CouldNotParseJson |
55            Self::CouldNotWriteToFile |
56            &Self::CouldNotReadFile |
57            // Self::DirectoryDoesNotExist |
58            Self::CouldNotConvertToJson => write!(f, "{:#?}", self)
59        }
60    }
61}
62
63#[derive(Debug)]
64pub struct ConfigError {
65    pub err_ty: ConfigErrorTy,
66    pub file: &'static str,
67    pub line: u32,
68    pub msg: Option<String>
69}
70
71impl Display for ConfigError {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        write!(f, "CONFIGURATION_ERROR: {}. file: {}, line: {}.", self.err_ty, self.file, self.line)?;
74        if let Some(msg) = &self.msg {
75            write!(f, "{}", msg)
76        } else {
77            Ok(())
78        }
79    }   
80}
81
82macro_rules! config_error {
83    ($err_ty:expr) => {
84        ConfigError {
85            err_ty: $err_ty,
86            file: file!(),
87            line: line!(),
88            msg: None
89        }
90    };
91    ($err_ty:expr, $msg:expr) => {
92        ConfigError {
93            err_ty: $err_ty,
94            file: file!(),
95            line: line!(),
96            msg: Some($msg.to_string())
97        }
98    };
99}
100    
101
102    #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord)]
103    pub struct GroupConfig {
104        pub priority: u16,
105        pub max_byte_size: Option<u64>,
106    }
107
108    #[derive(Debug, Deserialize, Serialize)]
109    pub struct StoreConfig {
110        pub host: Option<String>,
111        pub port: Option<u32>,
112        pub node_id: Option<u16>,
113        pub database: Option<String>,
114        pub leveldb_path: Option<PathBuf>,
115        pub file_storage: Option<bool>,
116        pub file_storage_path: Option<PathBuf>,
117        pub max_byte_size: Option<u64>,
118        pub groups: Option<Vec<GroupConfig>>,
119        pub no_update: Option<bool>,
120        pub update: Option<bool>
121    }
122
123    impl StoreConfig {
124        pub fn new() -> StoreConfig {
125            StoreConfig {
126                host: Some("127.0.0.1".to_string()),
127                port: Some(8080),
128                node_id: None,
129                database: Some("mem".to_string()),
130                leveldb_path: None,
131                file_storage: Some(false),
132                file_storage_path: None,
133                max_byte_size: None,
134                groups: None,
135                no_update: None,
136                update: Some(true)
137            }
138        }
139        pub fn open(config_path: &Path) -> Result<StoreConfig, ConfigError> {
140            let contents: String = match read_to_string(config_path) {
141                Ok(content) => Ok(content),
142                Err(err) => Err(config_error!(ConfigErrorTy::CouldNotReadFile, err))
143            }?;
144            match from_json_str(&contents) {
145                Ok(config) => Ok(config),
146                Err(err) => Err(config_error!(ConfigErrorTy::CouldNotParseJson, err))
147            }
148        }
149        pub fn update_config_file(&self, config_path: &Path) -> Result<(), ConfigError> {
150            let contents = match to_json_string(&self) {
151                Ok(contents) => Ok(contents),
152                Err(err) => Err(config_error!(ConfigErrorTy::CouldNotConvertToJson, err)),
153            }?;
154            if let Err(err) = fs::write(config_path, contents) {
155                return Err(config_error!(ConfigErrorTy::CouldNotWriteToFile, err));
156            };
157            Ok(())
158        }
159        pub fn to_json(&self) -> Result<String, ConfigError> {
160            match to_json_string(&self) {
161                Ok(json) => Ok(json),
162                Err(err) => Err(config_error!(ConfigErrorTy::CouldNotConvertToJson, err))
163            }
164        }
165        pub fn inherit(&mut self, configuration: Self) {
166            self.host = configuration.host;
167            self.port = configuration.port;
168            self.node_id = configuration.node_id;
169            self.database = configuration.database;
170            self.leveldb_path = configuration.leveldb_path;
171            self.file_storage = configuration.file_storage;
172            self.file_storage_path = configuration.file_storage_path;
173            self.max_byte_size = configuration.max_byte_size;
174            self.groups = configuration.groups;
175            self.no_update = configuration.no_update;
176        }
177    }
178
179    pub fn update_config(config: &StoreConfig, config_path: &Option<PathBuf>) -> Result<(), ConfigError> {
180        let should_update = {
181            let mut should_update = true;
182            if let Some(no_update) = config.no_update {
183                if no_update {
184                    should_update = false;
185                }
186            }
187            should_update
188        };
189        if should_update {
190            if let Some(config_path) = config_path {
191                config.update_config_file(&config_path)?;
192            }
193        }
194        Ok(())
195    }
196
197}