use std::path;
use serde::{
Serialize,
Deserialize,
};
use crate::event::DirectoryType;
use crate::control::ControlSocket;
use crate::control::argument::KeyArg;
pub const DEFAULT_CFG_FILE_NAME: &str = "./cnsprcy.tml";
pub const DEFAULT_PORT: u16 = 3030;
pub fn default_cfg_file_path() -> Option<path::PathBuf> {
Some(dirs::config_dir()?
.join("cnsprcy")
.join("cnsprcy.tml"))
}
pub fn default_db_path() -> Option<path::PathBuf> {
Some(dirs::data_dir()?
.join("cnsprcy")
.join("cnsprcy.db"))
}
#[tracing::instrument]
pub fn get_config<P: AsRef<path::Path> + std::fmt::Debug>(path: Option<P>)
-> ParseResult
{
match path {
Some(path) => try_parse_config_file(path),
None => match default_cfg_file_path() {
Some(path) => match try_parse_config_file(path) {
ParseResult::NotFound =>
try_parse_config_file(DEFAULT_CFG_FILE_NAME),
result => result
},
None => ParseResult::Err(
"Could not determine config file path!".to_string()
)
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Config {
pub cnsprcy: GeneralConfig,
pub server: ServerConfig,
pub handlers: Option<Vec<HandlerDirectory>>
}
pub enum ParseResult {
Ok(Config),
NotFound,
Err(String)
}
impl Config {
pub fn to_pretty_string(&self) -> String {
toml::to_string_pretty(self).unwrap_or_else(|e| {
panic!("Serializing config into TOML failed: {e}");
})
}
pub fn db_path(&self) -> path::PathBuf {
match self.cnsprcy.database.as_ref() {
Some(path) => path.clone(),
None => default_db_path()
.expect("could not determine XDG data base directory")
}
}
}
impl Default for Config {
fn default() -> Self {
Self {
cnsprcy: GeneralConfig {
database: default_db_path(),
control_socket_path: ControlSocket::default_path(),
key: KeyArg::random()
},
server: ServerConfig {
interfaces: None,
addrs: Some(vec![])
},
handlers: Some(vec![ HandlerDirectory {
r#type: None, path: dirs::data_dir()
.or_else(|| std::env::current_dir().ok())
.unwrap_or_else(|| ".".into())
.join("cnsprcy")
.join("handlers")
}])
}
}
}
#[tracing::instrument]
pub fn try_parse_config_file<P>(path: P) -> ParseResult
where P: AsRef<path::Path> + std::fmt::Debug
{
if !path.as_ref().exists() {
return ParseResult::NotFound;
}
match std::fs::read_to_string(path) {
Ok(toml_str) => match toml::from_str::<Config>(&toml_str) {
Ok(cfg) => ParseResult::Ok(cfg),
Err(e) => ParseResult::Err(
format!("Could not parse config file: {e}!")
)
},
Err(e) => ParseResult::Err(
format!("Could not read config file: {e}!")
)
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct GeneralConfig {
pub control_socket_path: path::PathBuf,
pub database: Option<path::PathBuf>,
pub key: KeyArg
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ServerConfig {
pub interfaces: Option<Vec<String>>,
pub addrs: Option<Vec<String>>
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct HandlerDirectory {
pub r#type: Option<DirectoryType>,
pub path: path::PathBuf
}