use json::{object, JsonValue};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fs;
use std::path::PathBuf;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Config {
pub default: String,
pub connections: BTreeMap<String, Connection>,
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
impl Config {
pub fn create(config_file: PathBuf, pkg_name: bool) -> Config {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ConfigNew {
pub br_cache: Config,
}
impl ConfigNew {
pub fn new() -> ConfigNew {
let mut connections = BTreeMap::new();
connections.insert("my_name".to_string(), Connection::default());
Self {
br_cache: Config {
default: "my_name".to_string(),
connections,
},
}
}
}
match fs::read_to_string(config_file.clone()) {
Ok(e) => {
if pkg_name {
let data = ConfigNew::new();
toml::from_str::<ConfigNew>(&e)
.unwrap_or_else(|_| {
let toml = toml::to_string(&data).unwrap();
let toml = format!("{e}\r\n{toml}");
let _ = fs::write(config_file.to_str().unwrap(), toml);
data
})
.br_cache
} else {
Config::new()
}
}
Err(_) => {
if pkg_name {
let data = ConfigNew::new();
fs::create_dir_all(config_file.parent().unwrap()).unwrap();
let toml = toml::to_string(&data).unwrap();
let _ = fs::write(config_file.to_str().unwrap(), toml);
data.br_cache
} else {
let data = Config::new();
fs::create_dir_all(config_file.parent().unwrap()).unwrap();
let toml = toml::to_string(&data).unwrap();
let _ = fs::write(config_file.to_str().unwrap(), toml);
data
}
}
}
}
pub fn new() -> Config {
let mut connections = BTreeMap::new();
connections.insert("my_name".to_string(), Connection::default());
Self {
default: "my_name".to_string(),
connections,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Connection {
pub mode: CacheMode,
pub hostname: String,
pub hostport: String,
pub userpass: String,
#[serde(default)]
pub kafka: Option<KafkaConnection>,
}
impl Default for Connection {
fn default() -> Self {
Self {
mode: CacheMode::Redis,
hostname: "127.0.0.1".to_string(),
hostport: "6379".to_string(),
userpass: "".to_string(),
kafka: None,
}
}
}
impl Connection {
pub fn from(data: JsonValue) -> Connection {
let kafka = if data["kafka"].is_object() {
Some(KafkaConnection::from(data["kafka"].clone()))
} else {
None
};
Self {
mode: CacheMode::from(data["mode"].as_str().unwrap_or("")),
hostname: data["hostname"].to_string(),
hostport: data["hostport"].to_string(),
userpass: data["userpass"].to_string(),
kafka,
}
}
pub fn json(&mut self) -> JsonValue {
let mut data = object! {};
data["mode"] = self.mode.str().into();
data["hostname"] = self.hostname.clone().into();
data["hostport"] = self.hostport.clone().into();
data["userpass"] = self.userpass.clone().into();
if let Some(ref kafka) = self.kafka {
data["kafka"] = kafka.json();
}
data
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum CacheMode {
Redis,
Kafka,
None,
}
impl CacheMode {
pub fn str(&self) -> &'static str {
match self {
CacheMode::Redis => "redis",
CacheMode::Kafka => "kafka",
CacheMode::None => "",
}
}
pub fn from(name: &str) -> Self {
match name {
"redis" => CacheMode::Redis,
"kafka" => CacheMode::Kafka,
_ => CacheMode::Redis,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KafkaConnection {
pub brokers: Vec<String>,
pub fetch_max: i32,
pub retry_max: i32,
}
impl Default for KafkaConnection {
fn default() -> Self {
Self {
brokers: vec!["127.0.0.1:9092".to_string()],
fetch_max: 1048576,
retry_max: 10485760,
}
}
}
impl KafkaConnection {
pub fn from(data: JsonValue) -> Self {
let brokers = data["brokers"]
.members()
.map(|x| x.as_str().unwrap_or("").to_string())
.filter(|x| !x.is_empty())
.collect();
Self {
brokers,
fetch_max: data["fetch_max"].as_i32().unwrap_or(1048576),
retry_max: data["retry_max"].as_i32().unwrap_or(10485760),
}
}
pub fn json(&self) -> JsonValue {
object! {
brokers: self.brokers.clone(),
fetch_max: self.fetch_max,
retry_max: self.retry_max
}
}
}