redis_macros/
lib.rs

1//! Simple macros and wrappers to [redis-rs](https://github.com/redis-rs/redis-rs/)
2//! to automatically serialize and deserialize structs with serde.
3//!
4//! ## Simple usage
5//!
6//! The simplest way to start is to derive `Serialize`, `Deserialize`,
7//! [`FromRedisValue`], [`ToRedisArgs`] for any kind of struct... and that's it!
8//! You can now get and set these values with regular redis commands:
9//!
10//! ```rust,no_run
11//! use redis::{Client, Commands, RedisResult};
12//! use redis_macros_derive::{FromRedisValue, ToRedisArgs};
13//! use serde::{Deserialize, Serialize};
14//!
15//! #[derive(Serialize, Deserialize)]
16//! enum Address {
17//!     Street(String),
18//!     Road(String),
19//! }
20//!
21//! // Derive the necessary traits
22//! #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
23//! struct User {
24//!     id: u32,
25//!     name: String,
26//!     addresses: Vec<Address>,
27//! }
28//!
29//! fn main () -> redis::RedisResult<()> {
30//!     let client = redis::Client::open("redis://localhost:6379/")?;
31//!     let mut con = client.get_connection()?;
32//!
33//!     let user = User {
34//!         id: 1,
35//!         name: "Ziggy".to_string(),
36//!         addresses: vec![
37//!             Address::Street("Downing".to_string()),
38//!             Address::Road("Abbey".to_string()),
39//!         ],
40//!     };
41//!
42//!     // Just use it as you would a primitive
43//!     con.set("user", user)?;
44//!     // user and stored_user will be the same
45//!     let stored_user: User = con.get("user")?;
46//!     # Ok(())
47//! }
48//! ```
49//!
50//! ## Usage with RedisJSON
51//!
52//! You can even use it with RedisJSON, to extract separate parts of the object.
53//!
54//! ```rust,no_run
55//! # use redis::{Client, RedisResult};
56//! use redis::JsonCommands;
57//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
58//! # use serde::{Deserialize, Serialize};
59//!
60//! // Derive FromRedisValue, ToRedisArgs to the inner struct
61//! #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
62//! enum Address { Street(String), Road(String) }
63//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
64//! # struct User { id: u32, name: String, addresses: Vec<Address> }
65//!
66//! # fn main () -> redis::RedisResult<()> {
67//! # let client = redis::Client::open("redis://localhost:6379/")?;
68//! # let mut con = client.get_connection()?;
69//! # let user = User { id: 1, name: "Ziggy".to_string(), addresses: vec![ Address::Street("Downing".to_string()), Address::Road("Abbey".to_string()) ] };
70//! // Simple usage is equivalent to set-get
71//! con.json_set("user", "$", &user)?;
72//! let stored_user: User = con.json_get("user", "$")?;
73//!
74//! // But you can get deep values - don't forget to derive traits for these too!
75//! let stored_address: Address = con.json_get("user", "$.addresses[0]")?;
76//! # Ok(())
77//! # }
78//! ```
79//!
80//! One issue you might be facing is that `redis` already has overrides for some types,
81//! for example Vec, String and most primitives. For this you have to use the [Json wrapper](#json-wrapper-with-redisjson).
82//!
83//! ```rust,no_run
84//! # use redis::{Client, JsonCommands, RedisResult};
85//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
86//! # use serde::{Deserialize, Serialize};
87//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
88//! # enum Address { Street(String), Road(String) }
89//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
90//! # struct User { id: u32, name: String, addresses: Vec<Address> }
91//! # fn main () -> redis::RedisResult<()> {
92//! # let client = redis::Client::open("redis://localhost:6379/")?;
93//! # let mut con = client.get_connection()?;
94//! # let user = User { id: 1, name: "Ziggy".to_string(), addresses: vec![ Address::Street("Downing".to_string()), Address::Road("Abbey".to_string()) ] };
95//! # con.json_set("user", "$", &user)?;
96//! // This WON'T work
97//! let stored_addresses: Vec<Address> = con.json_get("user", "$.addresses")?;
98//! # Ok(())
99//! # }
100//! ```
101//!
102//! ## Json wrapper with RedisJSON
103//!
104//! To deserialize Vecs and primitive types when using RedisJSON, you cannot use the regular types,
105//! because these are non-compatible with RedisJSON. However `redis-macros` exports a useful wrapper
106//! struct: [`Json`]. When using RedisJSON, you can wrap your non-structs return values into this:
107//!
108//! ```rust,no_run
109//! use redis_macros::Json;
110//! # use redis::{Client, JsonCommands, RedisResult};
111//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
112//! # use serde::{Deserialize, Serialize};
113//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
114//! # enum Address { Street(String), Road(String) }
115//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
116//! # struct User { id: u32, name: String, addresses: Vec<Address> }
117//! # fn main () -> redis::RedisResult<()> {
118//! # let client = redis::Client::open("redis://localhost:6379/")?;
119//! # let mut con = client.get_connection()?;
120//! # let user = User { id: 1, name: "Ziggy".to_string(), addresses: vec![ Address::Street("Downing".to_string()), Address::Road("Abbey".to_string()) ] };
121//! # con.json_set("user", "$", &user)?;
122
123//! // Return type can be wrapped into Json
124//! let Json(stored_name): Json<String> = con.json_get("user", "$.name")?;
125//!
126//! // It works with Vecs as well
127//! let Json(stored_addresses): Json<Vec<Address>> = con.json_get("user", "$.addresses")?;
128//! // ...now stored_addresses will be equal to user.addresses
129//! # Ok(())
130//! # }
131//! ```
132//!
133//! If you only use RedisJSON, you can even do away with deriving `FromRedisValue` and `ToRedisArgs`, and use `Json` everywhere.
134//!
135//! ```rust,no_run
136//! # use redis::{Client, JsonCommands, RedisResult};
137//! # use redis_macros::Json;
138//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
139//! # use serde::{Deserialize, Serialize};
140//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
141//! # enum Address { Street(String), Road(String) }
142//! #[derive(Serialize, Deserialize)]
143//! struct User { /* .. */ }
144//! # fn main () -> redis::RedisResult<()> {
145//! # let client = redis::Client::open("redis://localhost:6379/")?;
146//! # let mut con = client.get_connection()?;
147//! # let user = User {};
148//! # con.json_set("user", "$", &user)?;
149//!
150//! // This works with simple redis-rs
151//! con.json_set("user", "$", &user)?;
152//! // ...and you can get back with Json wrapper
153//! let Json(stored_user): Json<User> = con.json_get("user", "$")?;
154//! # Ok(())
155//! # }
156//! ```
157//!
158//! ## Using other serializer (e.g. serde-yaml)
159//!
160//! In case you want to use another serializer, for example `serde_yaml`, you can install it and use the derives,
161//! the same way you would. The only difference should be adding an attribute `redis_serializer` under the derive,
162//! with the library you want to serialize with. You can use any Serde serializer as long as they support
163//! `from_str` and `to_string` methods. For the full list, see: [Serde data formats](https://serde.rs/#data-formats).
164//!
165//! ```rust,no_run
166//! # use redis::{Client, JsonCommands, RedisResult};
167//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
168//! # use serde::{Deserialize, Serialize};
169//!
170//! #[derive(Debug, PartialEq, Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
171//! #[redis_serializer(serde_yaml)]
172//! struct User { /* ... */ }
173//! ```
174
175#[cfg(feature = "macros")]
176extern crate redis_macros_derive;
177
178#[cfg(feature = "json")]
179mod json;
180
181#[cfg(feature = "json")]
182pub use json::Json;
183
184/// Derive macro for the redis crate's [`FromRedisValue`](../redis/trait.FromRedisValue.html) trait to allow parsing Redis responses to this type.
185/// 
186/// For more information see the `redis_macros_derive` crate: [`FromRedisValue`](../redis_macros_derive/derive.FromRedisValue.html)
187#[cfg(feature = "macros")]
188pub use redis_macros_derive::FromRedisValue;
189
190/// Derive macro for the redis crate's [`ToRedisArgs`](../redis/trait.ToRedisArgs.html) trait to allow passing the type to Redis commands.
191/// 
192/// For more information see the `redis_macros_derive` crate: [`ToRedisArgs`](../redis_macros_derive/derive.FromRedisValue.html)
193#[cfg(feature = "macros")]
194pub use redis_macros_derive::ToRedisArgs;