use std::collections::HashMap;
use std::{fs};
use json::{array, JsonValue, object};
use crate::redis::Redis;
pub mod redis;
#[derive(Clone)]
pub enum Cache {
Redis(Redis),
None,
}
impl Cache {
pub fn load(path: &str) -> Self {
let config = match fs::read_to_string(path) {
Ok(e) => {
match json::parse(e.as_str()) {
Ok(e) => e,
Err(_) => {
let mut res = CacheConfig::default();
fs::write(path, res.json().to_string()).unwrap();
res.json()
}
}
}
Err(_) => {
let mut res = CacheConfig::default();
fs::write(path, res.json().to_string()).unwrap();
res.json()
}
};
Cache::connect(config)
}
pub fn connect(config: JsonValue) -> Self {
if config.is_empty() {
return Cache::None;
}
let config = CacheConfig::from(config);
let connection = config.connections.get(&*config.default).clone().unwrap().clone();
match connection.mode {
CacheMode::Redis => {
Cache::Redis(Redis::connect(connection.get_dsn().clone()))
}
}
}
pub fn login(cache_mode: CacheMode, host: &str, port: &str, pass: &str) -> Self {
match cache_mode {
CacheMode::Redis => {
let dsn = if pass.is_empty() {
format!("redis://{host}:{port}/")
} else {
format!("redis://:{pass}@{host}:{port}/")
};
Cache::Redis(Redis::connect(dsn))
}
}
}
}
impl CacheBase for Cache {
fn db(&mut self, db: i8) -> &mut Self {
match self {
Cache::Redis(e) => {
e.db(db);
}
Cache::None => {}
}
self
}
fn add(&mut self, key: &str, value: JsonValue, expiration_date: u64) -> Result<bool, String> {
let res = match self {
Cache::Redis(e) => e.add(key, value, expiration_date)?,
Cache::None => false
};
Ok(res)
}
fn get(&mut self, key: &str) -> Result<JsonValue, String> {
let res = match self {
Cache::Redis(e) => e.get(key)?,
Cache::None => JsonValue::Null
};
Ok(res)
}
fn delete(&mut self, key: &str) -> Result<bool, String> {
let res = match self {
Cache::Redis(e) => e.delete(key)?,
Cache::None => false
};
Ok(res)
}
fn exists(&mut self, key: &str) -> Result<bool, String> {
let res = match self {
Cache::Redis(e) => e.exists(key)?,
Cache::None => false
};
Ok(res)
}
fn keys(&mut self, key: &str) -> Result<JsonValue, String> {
let res = match self {
Cache::Redis(e) => e.keys(key)?,
Cache::None => JsonValue::from(array![])
};
Ok(res)
}
fn set_add(&mut self, key: &str, value: JsonValue) -> Result<bool, String> {
let res = match self {
Cache::Redis(e) => e.set_add(key, value)?,
Cache::None => false
};
Ok(res)
}
fn set_get(&mut self, key: &str) -> Result<JsonValue, String> {
let res = match self {
Cache::Redis(e) => e.set_get(key)?,
Cache::None => array![]
};
Ok(res)
}
fn set_delete(&mut self, key: &str, value: JsonValue) -> Result<bool, String> {
let res = match self {
Cache::Redis(e) => e.set_delete(key, value)?,
Cache::None => false
};
Ok(res)
}
fn set_message_queue(&mut self, key: &str, value: JsonValue) -> bool {
match self {
Cache::Redis(e) => {
e.set_message_queue(key, value)
}
Cache::None => false
}
}
fn get_message_queue(&mut self, key: &str) -> JsonValue {
match self {
Cache::Redis(e) => {
e.get_message_queue(key)
}
Cache::None => array![]
}
}
fn set_object(&mut self, key: &str, field: &str, value: JsonValue) -> bool {
match self {
Cache::Redis(e) => {
e.set_object(key, field, value)
}
Cache::None => false
}
}
fn get_object(&mut self, key: &str) -> JsonValue {
match self {
Cache::Redis(e) => {
e.get_object(key)
}
Cache::None => object! {}
}
}
}
pub trait CacheBase {
fn db(&mut self, db: i8) -> &mut Self;
fn add(&mut self, key: &str, value: JsonValue, expiration_date: u64) -> Result<bool, String>;
fn get(&mut self, key: &str) -> Result<JsonValue, String>;
fn delete(&mut self, key: &str) -> Result<bool, String>;
fn exists(&mut self, key: &str) -> Result<bool, String>;
fn keys(&mut self, key: &str) -> Result<JsonValue, String>;
fn set_add(&mut self, key: &str, value: JsonValue) -> Result<bool, String>;
fn set_get(&mut self, key: &str) -> Result<JsonValue, String>;
fn set_delete(&mut self, key: &str, value: JsonValue) -> Result<bool, String>;
fn set_message_queue(&mut self, key: &str, value: JsonValue) -> bool;
fn get_message_queue(&mut self, key: &str) -> JsonValue;
fn set_object(&mut self, key: &str, field: &str, value: JsonValue) -> bool;
fn get_object(&mut self, key: &str) -> JsonValue;
}
#[derive(Clone)]
pub struct CacheConfig {
default: String,
connections: HashMap<String, Connection>,
}
impl CacheConfig {
pub fn default() -> CacheConfig {
let mut connections = HashMap::new();
connections.insert("my_name".to_string(), Connection::default());
Self {
default: "my_name".to_string(),
connections,
}
}
pub fn json(&mut self) -> JsonValue {
let mut data = object! {};
data["default"] = self.default.clone().into();
let mut connections = object! {};
for (name, connection) in self.connections.iter_mut() {
connections[name.clone()] = connection.json().clone();
}
data["connections"] = connections;
data
}
pub fn from(data: JsonValue) -> CacheConfig {
let default = data["default"].to_string();
let mut connections = HashMap::new();
for (key, value) in data["connections"].entries() {
let connection = Connection::default().from(value.clone()).clone();
connections.insert(key.to_string(), connection.clone());
}
Self {
default,
connections,
}
}
}
#[derive(Clone)]
struct Connection {
mode: CacheMode,
hostname: String,
hostport: String,
userpass: String,
}
impl Connection {
pub fn default() -> Connection {
Self {
mode: CacheMode::Redis,
hostname: "127.0.0.1".to_string(),
hostport: "6379".to_string(),
userpass: "".to_string(),
}
}
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();
data
}
pub fn from(&mut self, data: JsonValue) -> &mut Connection {
self.mode = CacheMode::from(data["mode"].as_str().unwrap());
self.hostname = data["hostname"].to_string();
self.hostport = data["hostport"].to_string();
self.userpass = data["userpass"].to_string();
self
}
pub fn get_dsn(self) -> String {
match self.mode {
CacheMode::Redis => {
if self.userpass != "" {
format!("redis://:{}@{}:{}/", self.userpass, self.hostname, self.hostport)
} else {
format!("redis://{}:{}/", self.hostname, self.hostport)
}
}
}
}
}
#[derive(Clone, Debug)]
pub enum CacheMode {
Redis,
}
impl CacheMode {
pub fn str(&mut self) -> String {
match self {
CacheMode::Redis => "redis"
}.to_string()
}
pub fn from(name: &str) -> Self {
match name {
"redis" => CacheMode::Redis,
_ => CacheMode::Redis
}
}
}