cache_any/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(feature = "redis", allow(dependency_on_unit_never_type_fallback))]

//! A cache library for Rust.
//! 
//! This library provides a trait [`Cache`] and some
//! implementations of it.
//! 
//! It defines the basic operations of a cache, for
//! example, [`caches::Cache::get`], [`caches::Cache::set`].
//! All functions are async, because we may use async storage backends.
//!
//! All caches are key-value based.
//! 
//! By default, it provides a simple memory cache as example. See [`caches::MemoryCache`].
//! But it's not recommended to use [`caches::MemoryCache`] directly in production.
//!
//! Other caches are available in below features:
//! 
//! * `redis`: Use redis as storage backend. See [`caches::RedisCache`].
//! * `mysql`: Use mysql as storage backend. See [`caches::MySqlCache`].
//! 
//! ## Usage
//! 
//! Add `cache-any` to your `Cargo.toml`:
//! 
//! ```toml
//! [dependencies]
//! cache-any = { version = "1", features = ["full"] }
//! ```
//! 
//! ## Concepts
//! 
//! * **Key**: Specified by the cache implementation. Usually it is a string-like type (&str, String, ...).
//! * **Value**: The value of a cache is a [`Cacheable`] value.
//! 
//! [`Cacheable`] is a trait that describes how to convert a `value` to bytes and vice versa.
//! 
//! A cache can store any value that implements [`Cacheable`].
//! That is, you can store usize and string (or any other types) at the same time.
//! But you need to know the exact type when you retrieve the value.
//! 
//! ## Basic Usage
//! 
//! We use [`caches::MemoryCache`] as example.
//! 
//! ```rust
//! let cache = MemoryCache::default();
//! 
//! // The cache is empty, so `get` returns None.
//! assert!(cache.get::<()>("non-existent-key").await.unwrap().is_none());
//! 
//! // [SET a -> 1]
//! cache.set("a", 1).await.unwrap();
//! 
//! // [GET a] -> Some(1)
//! let a_value: u8 = cache.get("a").await.unwrap().unwrap();
//! assert_eq!(a_value, 1);
//! 
//! // you can do type casting, using u16 instead of u8 as an example.
//! let a_value: u16 = cache.get("a").await.unwrap().unwrap();
//! assert_eq!(a_value, 1);
//! 
//! // you can also store [`String`] in the same cache:
//! cache.set("b", String::from("hello")).await.unwrap();
//! let b_value: String = cache.get("b").await.unwrap().unwrap();
//! assert_eq!(b_value, String::from("hello"));
//! ```
//! 
//! ## Extend Cacheable
//! 
//! You can extend [`Cacheable`] for your own types.
//! For example, you can define a struct and implement [`Cacheable`] for it.
//! 
//! ```rust
//! #[derive(serde::Serialize, serde::Deserialize)] // for json
//! struct MyStruct {
//!     a: u8,
//!     b: String,
//! }
//! ```
//! 
//! In this case, we use `serde_json` to convert the struct to bytes and vice versa.
//! 
//! ```rust,ignore
//! impl Cacheable for MyStruct {
//!     fn to_bytes(&self) -> Vec<u8> {
//!         serde_json::to_vec(self).unwrap()
//!     }
//!
//!     fn from_bytes(bytes: &[u8]) -> anyhow::Result<Self> {
//!         let ret = serde_json::from_slice(bytes)?;
//!         Ok(ret)
//!     }
//! }
//! ```
//! 
//! Then you can store `MyStruct` in the cache:
//! 
//! ```rust
//! cache.set("my-struct", MyStruct { a: 1, b: String::from("hello") }).await.unwrap();
//! ```
//!
//! ## Work in Progress
//! 
//! * Add examples for each cache implementation.
//!
//! ## Contributing
//! 
//! Any contributions are welcome.
//! 
//! If you find any useful cache implementation,
//! feel free to open an issue or a pull request at [Github](https://github.com/caojen/cache-any).
//! 
//! If bugs are found, just file an issue at [Github](https://github.com/caojen/cache-any), and I will fix it **ASAP**.
//! 
//! ## License
//! 
//! This project is licensed under the MIT License.

mod cacheable;
pub use cacheable::*;

mod caches;
pub use caches::*;

#[test]
fn it_works() {
    println!("it works")
}