use crate::redis::apply_operator;
use redis::{Commands, RedisResult};
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::{Debug, Display};
use std::ops;
pub struct Generic<T> {
pub(crate) cache: Option<T>,
pub(crate) key: String,
pub(crate) client: redis::Client,
}
impl<T> Generic<T>
where
T: Serialize + DeserializeOwned,
{
pub fn new(field_name: &str, client: redis::Client) -> Generic<T> {
Generic {
cache: None,
key: field_name.to_string(),
client,
}
}
pub fn with_value(value: T, field_name: &str, client: redis::Client) -> Generic<T> {
let mut new_type = Self::new(field_name, client);
new_type.store(value);
new_type
}
pub fn with_load(field_name: &str, client: redis::Client) -> Generic<T> {
let mut new_type = Self::new(field_name, client);
new_type.cache = new_type.try_get();
new_type
}
pub fn with_value_default(value: T, field_name: &str, client: redis::Client) -> Generic<T> {
let mut new_type = Self::new(field_name, client);
let v = new_type.try_get();
if v.is_none() {
new_type.store(value);
} else {
new_type.cache = v;
}
new_type
}
pub fn store(&mut self, value: T) {
let value = self.set(value);
self.cache = Some(value);
}
fn set(&self, value: T) -> T {
let mut conn = self.get_conn();
let v = serde_json::to_string(&value).expect("Failed to serialize value");
let res: RedisResult<()> = conn.set(&self.key, v);
res.expect("Failed to set value");
value
}
fn pushes_to_redis(&self) {
if self.cache.is_none() {
return;
}
let mut conn = self.get_conn();
let v = serde_json::to_string(&self.cache).expect("Failed to serialize value");
let res: RedisResult<()> = conn.set(&self.key, v);
res.expect("Failed to set value");
}
pub fn acquire(&mut self) -> &T {
self.cache = self.try_get();
self.cache.as_ref().unwrap()
}
fn try_get(&self) -> Option<T> {
let mut conn = self.get_conn();
let res: RedisResult<String> = conn.get(&self.key);
match res {
Ok(v) => {
let v: T = serde_json::from_str(&v).expect("Failed to deserialize value");
Some(v)
}
Err(_) => None,
}
}
pub fn into_inner(mut self) -> T {
let mut conn = self
.client
.get_connection()
.expect("Failed to get connection");
let _: RedisResult<()> = conn.del(&self.key);
self.cache.take().expect("Failed to get value")
}
pub(crate) fn get_conn(&self) -> redis::Connection {
self.client
.get_connection()
.expect("Failed to get connection")
}
pub fn cached(&self) -> Option<&T> {
self.cache.as_ref()
}
}
impl<T> ops::Deref for Generic<T>
where
T: Display + Serialize + DeserializeOwned,
{
type Target = T;
fn deref(&self) -> &Self::Target {
self.cached().expect("Failed to get value")
}
}
impl<T> ops::Add<T> for Generic<T>
where
T: ops::Add<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn add(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a + b)
}
}
impl<T> ops::Add<Generic<T>> for Generic<T>
where
T: ops::Add<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn add(self, rhs: Generic<T>) -> Self::Output {
self + rhs.into_inner()
}
}
impl<T> ops::Sub<T> for Generic<T>
where
T: ops::Sub<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn sub(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a - b)
}
}
impl<T> ops::Sub<Generic<T>> for Generic<T>
where
T: ops::Sub<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn sub(self, rhs: Generic<T>) -> Self::Output {
self - rhs.into_inner()
}
}
impl<T> ops::Mul<T> for Generic<T>
where
T: ops::Mul<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn mul(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a * b)
}
}
impl<T> ops::Mul<Generic<T>> for Generic<T>
where
T: ops::Mul<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn mul(self, rhs: Generic<T>) -> Self::Output {
self * rhs.into_inner()
}
}
impl<T> ops::Div<T> for Generic<T>
where
T: ops::Div<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn div(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a / b)
}
}
impl<T> ops::Div<Generic<T>> for Generic<T>
where
T: ops::Div<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn div(self, rhs: Generic<T>) -> Self::Output {
self / rhs.into_inner()
}
}
impl<T> ops::AddAssign<T> for Generic<T>
where
T: ops::AddAssign + Display + Serialize + DeserializeOwned,
{
fn add_assign(&mut self, rhs: T) {
if let Some(ref mut v) = self.cache {
*v += rhs;
} else {
self.cache = Some(rhs);
}
self.pushes_to_redis();
}
}
impl<T> ops::AddAssign<Generic<T>> for Generic<T>
where
T: ops::AddAssign + Display + Serialize + DeserializeOwned,
{
fn add_assign(&mut self, rhs: Generic<T>) {
*self += rhs.into_inner();
}
}
impl<T> ops::SubAssign<T> for Generic<T>
where
T: ops::SubAssign + Display + Serialize + DeserializeOwned,
{
fn sub_assign(&mut self, rhs: T) {
if let Some(ref mut v) = self.cache {
*v -= rhs;
} else {
self.cache = Some(rhs);
}
self.pushes_to_redis();
}
}
impl<T> ops::SubAssign<Generic<T>> for Generic<T>
where
T: ops::SubAssign + Display + Serialize + DeserializeOwned,
{
fn sub_assign(&mut self, rhs: Generic<T>) {
*self -= rhs.into_inner();
}
}
impl<T> ops::BitOr<T> for Generic<T>
where
T: ops::BitOr<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn bitor(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a | b)
}
}
impl<T> ops::BitOr<Generic<T>> for Generic<T>
where
T: ops::BitOr<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn bitor(self, rhs: Generic<T>) -> Self::Output {
self | rhs.into_inner()
}
}
impl<T> ops::BitAnd<T> for Generic<T>
where
T: ops::BitAnd<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn bitand(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a & b)
}
}
impl<T> ops::BitAnd<Generic<T>> for Generic<T>
where
T: ops::BitAnd<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn bitand(self, rhs: Generic<T>) -> Self::Output {
self & rhs.into_inner()
}
}
impl<T> ops::BitXor<T> for Generic<T>
where
T: ops::BitXor<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn bitxor(self, rhs: T) -> Self::Output {
apply_operator(self, rhs, |a, b| a ^ b)
}
}
impl<T> ops::BitXor<Generic<T>> for Generic<T>
where
T: ops::BitXor<Output = T> + Display + Serialize + DeserializeOwned,
{
type Output = Generic<T>;
fn bitxor(self, rhs: Generic<T>) -> Self::Output {
self ^ rhs.into_inner()
}
}
impl<T: PartialEq> PartialEq<T> for Generic<T> {
fn eq(&self, other: &T) -> bool {
self.cache.as_ref() == Some(other)
}
}
impl<T: PartialEq> PartialEq<Generic<T>> for Generic<T> {
fn eq(&self, other: &Generic<T>) -> bool {
self.cache == other.cache
}
}
impl<T: Debug> Debug for Generic<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Generic")
.field("value", &self.cache)
.field("field_name", &self.key)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_partialeq() {
let s1 = Generic::with_value(
2,
"test_partialeq",
redis::Client::open("redis://localhost/").unwrap(),
);
assert_eq!(s1, 2);
}
}