br-cache 0.3.22

This is an Cache and Message Queue abstraction layer
Documentation
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 {
    /// 创建配置
    /// *config_file 配置文件地址
    /// *path 是否显示包名
    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
        }
    }
}