dtypes/redis/
generic.rs

1//! This module contains the generic type.
2use crate::redis::apply_operator;
3use redis::{Commands, RedisResult};
4use serde::{de::DeserializeOwned, Serialize};
5use std::fmt::{Debug, Display};
6use std::ops;
7
8/// The generic type is used to implement the common methods for all types.
9///
10/// The generic type is not meant to be used directly. Instead use one of the aliases.
11///
12/// Mostly you will interact with the methods [Generic::store], [Generic::acquire] and [Generic::into_inner].
13pub struct Generic<T> {
14    pub(crate) cache: Option<T>,
15    pub(crate) key: String,
16    pub(crate) client: redis::Client,
17}
18
19impl<T> Generic<T>
20where
21    T: Serialize + DeserializeOwned,
22{
23    /// The new method creates a new instance of the type.
24    /// It does not load or store any value in Redis.
25    /// It only creates the instance.
26    ///
27    /// # Example
28    ///
29    /// ```
30    /// use dtypes::redis::types::Di32 as i32;
31    ///
32    /// let client = redis::Client::open("redis://localhost:6379").unwrap();
33    /// let mut i32 = i32::new("test_add", client.clone());
34    /// i32.store(1);
35    /// let i32 = i32 + i32::with_value(2, "test_add2", client);
36    /// assert_eq!(i32, 3);
37    /// ```
38    pub fn new(field_name: &str, client: redis::Client) -> Generic<T> {
39        Generic {
40            cache: None,
41            key: field_name.to_string(),
42            client,
43        }
44    }
45
46    /// The with_value method creates a new instance of the type.
47    /// If a value is already stored in Redis, it will be overwritten.
48    pub fn with_value(value: T, field_name: &str, client: redis::Client) -> Generic<T> {
49        let mut new_type = Self::new(field_name, client);
50
51        new_type.store(value);
52        new_type
53    }
54
55    /// The with_value_load method creates a new instance of the type.
56    /// It loads the value from Redis.
57    /// If there is no value stored in Redis, it stores a None in cache.
58    pub fn with_load(field_name: &str, client: redis::Client) -> Generic<T> {
59        let mut new_type = Self::new(field_name, client);
60
61        new_type.cache = new_type.try_get();
62        new_type
63    }
64
65    /// The with_value_default method creates a new instance of the type.
66    /// If the value is not already stored in Redis, it will be stored.
67    /// If the value is already stored in Redis, it will be loaded and your given value will be ignored.
68    pub fn with_value_default(value: T, field_name: &str, client: redis::Client) -> Generic<T> {
69        let mut new_type = Self::new(field_name, client);
70
71        let v = new_type.try_get();
72        if v.is_none() {
73            new_type.store(value);
74        } else {
75            new_type.cache = v;
76        }
77
78        new_type
79    }
80
81    /// The store method sets the value of the type.
82    pub fn store(&mut self, value: T) {
83        let value = self.set(value);
84        self.cache = Some(value);
85    }
86
87    /// The set method sets the value of the type in redis.
88    /// It does not update the cache.
89    /// This is useful if you want to store a value in redis without updating the cache.
90    fn set(&self, value: T) -> T {
91        let mut conn = self.get_conn();
92        let v = serde_json::to_string(&value).expect("Failed to serialize value");
93        let res: RedisResult<()> = conn.set(&self.key, v);
94        res.expect("Failed to set value");
95        value
96    }
97
98    /// Pushes the cache to redis.
99    fn pushes_to_redis(&self) {
100        if self.cache.is_none() {
101            return;
102        }
103        let mut conn = self.get_conn();
104        let v = serde_json::to_string(&self.cache).expect("Failed to serialize value");
105        let res: RedisResult<()> = conn.set(&self.key, v);
106        res.expect("Failed to set value");
107    }
108
109    /// The acquire method returns a reference to the value stored in the type.
110    /// Loads it from the redis directly.
111    ///
112    /// # Example
113    ///
114    /// ```
115    /// use dtypes::redis::types::Di32 as i32;
116    ///
117    /// let client = redis::Client::open("redis://localhost:6379").unwrap();
118    /// let mut i32 = i32::with_value(1, "test_add", client.clone());
119    /// i32 = i32 + i32::with_value(2, "test_add2", client);
120    /// assert_eq!(i32.acquire(), &3);
121    /// ```
122    pub fn acquire(&mut self) -> &T {
123        self.cache = self.try_get();
124        self.cache.as_ref().unwrap()
125    }
126
127    fn try_get(&self) -> Option<T> {
128        let mut conn = self.get_conn();
129        let res: RedisResult<String> = conn.get(&self.key);
130        match res {
131            Ok(v) => {
132                let v: T = serde_json::from_str(&v).expect("Failed to deserialize value");
133                Some(v)
134            }
135            Err(_) => None,
136        }
137    }
138
139    /// The into_inner method returns the inner value of the type.
140    /// This method consumes the type and drops everything.
141    ///
142    /// # Example
143    ///
144    /// ```
145    /// use dtypes::redis::types::Di32 as i32;
146    ///
147    /// let client = redis::Client::open("redis://localhost:6379").unwrap();
148    /// let i32 = i32::with_value(3, "test_add", client.clone());
149    /// let i32_inner = i32.into_inner();
150    /// assert_eq!(i32_inner, 3);
151    /// ```
152    pub fn into_inner(mut self) -> T {
153        let mut conn = self
154            .client
155            .get_connection()
156            .expect("Failed to get connection");
157        let _: RedisResult<()> = conn.del(&self.key);
158        self.cache.take().expect("Failed to get value")
159    }
160
161    /// The get_conn method returns a connection to Redis.
162    // FIXME: This should store a persistent connection for performance.
163    pub(crate) fn get_conn(&self) -> redis::Connection {
164        self.client
165            .get_connection()
166            .expect("Failed to get connection")
167    }
168
169    /// The get method returns a reference to the value stored in the type.
170    pub fn cached(&self) -> Option<&T> {
171        self.cache.as_ref()
172    }
173}
174
175impl<T> ops::Deref for Generic<T>
176where
177    T: Display + Serialize + DeserializeOwned,
178{
179    type Target = T;
180
181    fn deref(&self) -> &Self::Target {
182        self.cached().expect("Failed to get value")
183    }
184}
185
186impl<T> ops::Add<T> for Generic<T>
187where
188    T: ops::Add<Output = T> + Display + Serialize + DeserializeOwned,
189{
190    type Output = Generic<T>;
191
192    fn add(self, rhs: T) -> Self::Output {
193        apply_operator(self, rhs, |a, b| a + b)
194    }
195}
196
197impl<T> ops::Add<Generic<T>> for Generic<T>
198where
199    T: ops::Add<Output = T> + Display + Serialize + DeserializeOwned,
200{
201    type Output = Generic<T>;
202
203    fn add(self, rhs: Generic<T>) -> Self::Output {
204        self + rhs.into_inner()
205    }
206}
207
208impl<T> ops::Sub<T> for Generic<T>
209where
210    T: ops::Sub<Output = T> + Display + Serialize + DeserializeOwned,
211{
212    type Output = Generic<T>;
213
214    fn sub(self, rhs: T) -> Self::Output {
215        apply_operator(self, rhs, |a, b| a - b)
216    }
217}
218
219impl<T> ops::Sub<Generic<T>> for Generic<T>
220where
221    T: ops::Sub<Output = T> + Display + Serialize + DeserializeOwned,
222{
223    type Output = Generic<T>;
224
225    fn sub(self, rhs: Generic<T>) -> Self::Output {
226        self - rhs.into_inner()
227    }
228}
229
230impl<T> ops::Mul<T> for Generic<T>
231where
232    T: ops::Mul<Output = T> + Display + Serialize + DeserializeOwned,
233{
234    type Output = Generic<T>;
235
236    fn mul(self, rhs: T) -> Self::Output {
237        apply_operator(self, rhs, |a, b| a * b)
238    }
239}
240
241impl<T> ops::Mul<Generic<T>> for Generic<T>
242where
243    T: ops::Mul<Output = T> + Display + Serialize + DeserializeOwned,
244{
245    type Output = Generic<T>;
246
247    fn mul(self, rhs: Generic<T>) -> Self::Output {
248        self * rhs.into_inner()
249    }
250}
251
252impl<T> ops::Div<T> for Generic<T>
253where
254    T: ops::Div<Output = T> + Display + Serialize + DeserializeOwned,
255{
256    type Output = Generic<T>;
257
258    fn div(self, rhs: T) -> Self::Output {
259        apply_operator(self, rhs, |a, b| a / b)
260    }
261}
262
263impl<T> ops::Div<Generic<T>> for Generic<T>
264where
265    T: ops::Div<Output = T> + Display + Serialize + DeserializeOwned,
266{
267    type Output = Generic<T>;
268
269    fn div(self, rhs: Generic<T>) -> Self::Output {
270        self / rhs.into_inner()
271    }
272}
273
274impl<T> ops::AddAssign<T> for Generic<T>
275where
276    T: ops::AddAssign + Display + Serialize + DeserializeOwned,
277{
278    fn add_assign(&mut self, rhs: T) {
279        if let Some(ref mut v) = self.cache {
280            *v += rhs;
281        } else {
282            self.cache = Some(rhs);
283        }
284
285        self.pushes_to_redis();
286    }
287}
288
289impl<T> ops::AddAssign<Generic<T>> for Generic<T>
290where
291    T: ops::AddAssign + Display + Serialize + DeserializeOwned,
292{
293    fn add_assign(&mut self, rhs: Generic<T>) {
294        *self += rhs.into_inner();
295    }
296}
297
298impl<T> ops::SubAssign<T> for Generic<T>
299where
300    T: ops::SubAssign + Display + Serialize + DeserializeOwned,
301{
302    fn sub_assign(&mut self, rhs: T) {
303        if let Some(ref mut v) = self.cache {
304            *v -= rhs;
305        } else {
306            self.cache = Some(rhs);
307        }
308
309        self.pushes_to_redis();
310    }
311}
312
313impl<T> ops::SubAssign<Generic<T>> for Generic<T>
314where
315    T: ops::SubAssign + Display + Serialize + DeserializeOwned,
316{
317    fn sub_assign(&mut self, rhs: Generic<T>) {
318        *self -= rhs.into_inner();
319    }
320}
321
322impl<T> ops::BitOr<T> for Generic<T>
323where
324    T: ops::BitOr<Output = T> + Display + Serialize + DeserializeOwned,
325{
326    type Output = Generic<T>;
327
328    fn bitor(self, rhs: T) -> Self::Output {
329        apply_operator(self, rhs, |a, b| a | b)
330    }
331}
332
333impl<T> ops::BitOr<Generic<T>> for Generic<T>
334where
335    T: ops::BitOr<Output = T> + Display + Serialize + DeserializeOwned,
336{
337    type Output = Generic<T>;
338
339    fn bitor(self, rhs: Generic<T>) -> Self::Output {
340        self | rhs.into_inner()
341    }
342}
343
344impl<T> ops::BitAnd<T> for Generic<T>
345where
346    T: ops::BitAnd<Output = T> + Display + Serialize + DeserializeOwned,
347{
348    type Output = Generic<T>;
349
350    fn bitand(self, rhs: T) -> Self::Output {
351        apply_operator(self, rhs, |a, b| a & b)
352    }
353}
354
355impl<T> ops::BitAnd<Generic<T>> for Generic<T>
356where
357    T: ops::BitAnd<Output = T> + Display + Serialize + DeserializeOwned,
358{
359    type Output = Generic<T>;
360
361    fn bitand(self, rhs: Generic<T>) -> Self::Output {
362        self & rhs.into_inner()
363    }
364}
365
366impl<T> ops::BitXor<T> for Generic<T>
367where
368    T: ops::BitXor<Output = T> + Display + Serialize + DeserializeOwned,
369{
370    type Output = Generic<T>;
371
372    fn bitxor(self, rhs: T) -> Self::Output {
373        apply_operator(self, rhs, |a, b| a ^ b)
374    }
375}
376
377impl<T> ops::BitXor<Generic<T>> for Generic<T>
378where
379    T: ops::BitXor<Output = T> + Display + Serialize + DeserializeOwned,
380{
381    type Output = Generic<T>;
382
383    fn bitxor(self, rhs: Generic<T>) -> Self::Output {
384        self ^ rhs.into_inner()
385    }
386}
387
388impl<T: PartialEq> PartialEq<T> for Generic<T> {
389    fn eq(&self, other: &T) -> bool {
390        self.cache.as_ref() == Some(other)
391    }
392}
393
394impl<T: PartialEq> PartialEq<Generic<T>> for Generic<T> {
395    fn eq(&self, other: &Generic<T>) -> bool {
396        self.cache == other.cache
397    }
398}
399
400impl<T: Debug> Debug for Generic<T> {
401    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
402        f.debug_struct("Generic")
403            .field("value", &self.cache)
404            .field("field_name", &self.key)
405            .finish()
406    }
407}
408
409#[cfg(test)]
410mod tests {
411    use super::*;
412    #[test]
413    fn test_partialeq() {
414        let s1 = Generic::with_value(
415            2,
416            "test_partialeq",
417            redis::Client::open("redis://localhost/").unwrap(),
418        );
419        assert_eq!(s1, 2);
420    }
421}