redis_macros/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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
//! Simple macros and wrappers to [redis-rs](https://github.com/redis-rs/redis-rs/)
//! to automatically serialize and deserialize structs with serde.
//!
//! ## Simple usage
//!
//! The simplest way to start is to derive `Serialize`, `Deserialize`,
//! [`FromRedisValue`], [`ToRedisArgs`] for any kind of struct... and that's it!
//! You can now get and set these values with regular redis commands:
//!
//! ```rust,no_run
//! use redis::{Client, Commands, RedisResult};
//! use redis_macros_derive::{FromRedisValue, ToRedisArgs};
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Serialize, Deserialize)]
//! enum Address {
//! Street(String),
//! Road(String),
//! }
//!
//! // Derive the necessary traits
//! #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! struct User {
//! id: u32,
//! name: String,
//! addresses: Vec<Address>,
//! }
//!
//! fn main () -> redis::RedisResult<()> {
//! let client = redis::Client::open("redis://localhost:6379/")?;
//! let mut con = client.get_connection()?;
//!
//! let user = User {
//! id: 1,
//! name: "Ziggy".to_string(),
//! addresses: vec![
//! Address::Street("Downing".to_string()),
//! Address::Road("Abbey".to_string()),
//! ],
//! };
//!
//! // Just use it as you would a primitive
//! con.set("user", user)?;
//! // user and stored_user will be the same
//! let stored_user: User = con.get("user")?;
//! # Ok(())
//! }
//! ```
//!
//! ## Usage with RedisJSON
//!
//! You can even use it with RedisJSON, to extract separate parts of the object.
//!
//! ```rust,no_run
//! # use redis::{Client, RedisResult};
//! use redis::JsonCommands;
//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
//! # use serde::{Deserialize, Serialize};
//!
//! // Derive FromRedisValue, ToRedisArgs to the inner struct
//! #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! enum Address { Street(String), Road(String) }
//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! # struct User { id: u32, name: String, addresses: Vec<Address> }
//!
//! # fn main () -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://localhost:6379/")?;
//! # let mut con = client.get_connection()?;
//! # let user = User { id: 1, name: "Ziggy".to_string(), addresses: vec![ Address::Street("Downing".to_string()), Address::Road("Abbey".to_string()) ] };
//! // Simple usage is equivalent to set-get
//! con.json_set("user", "$", &user)?;
//! let stored_user: User = con.json_get("user", "$")?;
//!
//! // But you can get deep values - don't forget to derive traits for these too!
//! let stored_address: Address = con.json_get("user", "$.addresses[0]")?;
//! # Ok(())
//! # }
//! ```
//!
//! One issue you might be facing is that `redis` already has overrides for some types,
//! for example Vec, String and most primitives. For this you have to use the [Json wrapper](#json-wrapper-with-redisjson).
//!
//! ```rust,no_run
//! # use redis::{Client, JsonCommands, RedisResult};
//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
//! # use serde::{Deserialize, Serialize};
//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! # enum Address { Street(String), Road(String) }
//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! # struct User { id: u32, name: String, addresses: Vec<Address> }
//! # fn main () -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://localhost:6379/")?;
//! # let mut con = client.get_connection()?;
//! # let user = User { id: 1, name: "Ziggy".to_string(), addresses: vec![ Address::Street("Downing".to_string()), Address::Road("Abbey".to_string()) ] };
//! # con.json_set("user", "$", &user)?;
//! // This WON'T work
//! let stored_addresses: Vec<Address> = con.json_get("user", "$.addresses")?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Json wrapper with RedisJSON
//!
//! To deserialize Vecs and primitive types when using RedisJSON, you cannot use the regular types,
//! because these are non-compatible with RedisJSON. However `redis-macros` exports a useful wrapper
//! struct: [`Json`]. When using RedisJSON, you can wrap your non-structs return values into this:
//!
//! ```rust,no_run
//! use redis_macros::Json;
//! # use redis::{Client, JsonCommands, RedisResult};
//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
//! # use serde::{Deserialize, Serialize};
//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! # enum Address { Street(String), Road(String) }
//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! # struct User { id: u32, name: String, addresses: Vec<Address> }
//! # fn main () -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://localhost:6379/")?;
//! # let mut con = client.get_connection()?;
//! # let user = User { id: 1, name: "Ziggy".to_string(), addresses: vec![ Address::Street("Downing".to_string()), Address::Road("Abbey".to_string()) ] };
//! # con.json_set("user", "$", &user)?;
//! // Return type can be wrapped into Json
//! let Json(stored_name): Json<String> = con.json_get("user", "$.name")?;
//!
//! // It works with Vecs as well
//! let Json(stored_addresses): Json<Vec<Address>> = con.json_get("user", "$.addresses")?;
//! // ...now stored_addresses will be equal to user.addresses
//! # Ok(())
//! # }
//! ```
//!
//! If you only use RedisJSON, you can even do away with deriving `FromRedisValue` and `ToRedisArgs`, and use `Json` everywhere.
//!
//! ```rust,no_run
//! # use redis::{Client, JsonCommands, RedisResult};
//! # use redis_macros::Json;
//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
//! # use serde::{Deserialize, Serialize};
//! # #[derive(Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! # enum Address { Street(String), Road(String) }
//! #[derive(Serialize, Deserialize)]
//! struct User { /* .. */ }
//! # fn main () -> redis::RedisResult<()> {
//! # let client = redis::Client::open("redis://localhost:6379/")?;
//! # let mut con = client.get_connection()?;
//! # let user = User {};
//! # con.json_set("user", "$", &user)?;
//!
//! // This works with simple redis-rs
//! con.json_set("user", "$", &user)?;
//! // ...and you can get back with Json wrapper
//! let Json(stored_user): Json<User> = con.json_get("user", "$")?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Using other serializer (e.g. serde-yaml)
//!
//! In case you want to use another serializer, for example `serde_yaml`, you can install it and use the derives,
//! the same way you would. The only difference should be adding an attribute `redis_serializer` under the derive,
//! with the library you want to serialize with. You can use any Serde serializer as long as they support
//! `from_str` and `to_string` methods. For the full list, see: [Serde data formats](https://serde.rs/#data-formats).
//!
//! ```rust,no_run
//! # use redis::{Client, JsonCommands, RedisResult};
//! # use redis_macros_derive::{FromRedisValue, ToRedisArgs};
//! # use serde::{Deserialize, Serialize};
//!
//! #[derive(Debug, PartialEq, Serialize, Deserialize, FromRedisValue, ToRedisArgs)]
//! #[redis_serializer(serde_yaml)]
//! struct User { /* ... */ }
//! ```
#[cfg(feature = "macros")]
extern crate redis_macros_derive;
#[cfg(feature = "json")]
mod json;
#[cfg(feature = "json")]
pub use json::Json;
/// Derive macro for the redis crate's [`FromRedisValue`](../redis/trait.FromRedisValue.html) trait to allow parsing Redis responses to this type.
///
/// For more information see the `redis_macros_derive` crate: [`FromRedisValue`](../redis_macros_derive/derive.FromRedisValue.html)
#[cfg(feature = "macros")]
pub use redis_macros_derive::FromRedisValue;
/// Derive macro for the redis crate's [`ToRedisArgs`](../redis/trait.ToRedisArgs.html) trait to allow passing the type to Redis commands.
///
/// For more information see the `redis_macros_derive` crate: [`ToRedisArgs`](../redis_macros_derive/derive.FromRedisValue.html)
#[cfg(feature = "macros")]
pub use redis_macros_derive::ToRedisArgs;