use futures_util::future::BoxFuture;
use redis::ToRedisArgs;
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Serialize, Deserialize, Debug)]
pub struct RequestRedis {
pub(crate) id: String,
pub(crate) message: String,
pub(crate) reply_channel: String,
}
impl ToRedisArgs for RequestRedis {
fn write_redis_args<W>(&self, out: &mut W)
where
W: ?Sized + redis::RedisWrite,
{
let serialized = serde_json::to_string(self).unwrap();
serialized.write_redis_args(out);
}
}
#[derive(Clone)]
pub enum StateType {
None,
FunctionSync(Arc<dyn Fn(String) -> String + Sync + Send>),
FunctionAsync(Arc<dyn Fn(String) -> BoxFuture<'static, String> + Sync + Send>),
String(String),
Int(i32),
Float(f32),
Long(i64),
Double(f64),
AnyType(Arc<dyn Any + Sync + Send>),
}
macro_rules! impl_from_state_type {
($type: ty, $variant:ident) => {
impl From<StateType> for $type {
fn from(state: StateType) -> Self {
match state {
StateType::$variant(value) => value,
_ => panic!("Invalid conversion"),
}
}
}
};
}
impl_from_state_type!(i32, Int);
impl_from_state_type!(f32, Float);
impl_from_state_type!(i64, Long);
impl_from_state_type!(f64, Double);
impl_from_state_type!(String, String);
impl_from_state_type!(Arc<dyn Fn(String) -> BoxFuture<'static, String> + Sync + Send>, FunctionAsync);
impl_from_state_type!(Arc<dyn Fn(String) -> String + Sync + Send>, FunctionSync);
pub struct SharedState {
pub(crate) elements: RwLock<HashMap<String, StateType>>,
}
impl SharedState {
pub async fn get(&self, key: &String) -> StateType {
let elem_lock = self.elements.read().await;
let result = elem_lock.get(key);
match result {
None => StateType::None,
Some(value) => value.clone(),
}
}
pub async fn insert(&self, key: &String, data: StateType) {
let mut elem_lock = self.elements.write().await;
elem_lock.insert(key.clone(), data.clone());
drop(elem_lock);
}
pub async fn delete(&self, key: &String) {
let mut elem_lock = self.elements.write().await;
elem_lock.remove(key);
drop(elem_lock);
}
pub async fn get_any<T: 'static + Send + Sync>(&self, key: &String) -> Option<Arc<T>> {
let elem_lock = self.elements.read().await;
match elem_lock.get(key) {
Some(StateType::AnyType(value)) => value.clone().downcast::<T>().ok(),
_ => None,
}
}
}