fred/
lib.rs

1#![allow(clippy::unnecessary_fallible_conversions)]
2#![allow(clippy::redundant_pattern_matching)]
3#![allow(clippy::mutable_key_type)]
4#![allow(clippy::derivable_impls)]
5#![allow(clippy::enum_variant_names)]
6#![allow(clippy::iter_kv_map)]
7#![allow(clippy::len_without_is_empty)]
8#![allow(clippy::vec_init_then_push)]
9#![allow(clippy::while_let_on_iterator)]
10#![allow(clippy::type_complexity)]
11#![allow(clippy::too_many_arguments)]
12#![allow(clippy::new_without_default)]
13#![allow(clippy::assigning_clones)]
14#![allow(clippy::manual_async_fn)]
15#![warn(clippy::large_types_passed_by_value)]
16#![warn(clippy::large_stack_frames)]
17#![warn(clippy::large_futures)]
18#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
19#![cfg_attr(docsrs, feature(doc_cfg))]
20#![cfg_attr(docsrs, allow(unused_attributes))]
21#![doc = include_str!("../README.md")]
22
23#[cfg(any(feature = "dns", feature = "replicas"))]
24#[macro_use]
25#[allow(unused_imports)]
26extern crate async_trait;
27
28#[macro_use]
29extern crate log;
30
31pub extern crate bytes;
32pub extern crate bytes_utils;
33#[cfg(feature = "enable-native-tls")]
34#[cfg_attr(docsrs, doc(cfg(feature = "enable-native-tls")))]
35pub extern crate native_tls;
36#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))]
37#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))]
38pub extern crate rustls;
39#[cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))]
40#[cfg_attr(docsrs, doc(cfg(any(feature = "enable-rustls", feature = "enable-rustls-ring"))))]
41pub extern crate rustls_native_certs;
42#[cfg(feature = "serde-json")]
43pub extern crate serde_json;
44pub extern crate socket2;
45#[cfg(feature = "partial-tracing")]
46#[cfg_attr(docsrs, doc(cfg(feature = "partial-tracing")))]
47pub extern crate tracing;
48#[cfg(any(feature = "full-tracing", feature = "partial-tracing"))]
49extern crate tracing_futures;
50#[macro_use]
51mod macros;
52
53mod commands;
54mod modules;
55mod protocol;
56mod router;
57mod trace;
58mod utils;
59
60/// Redis client implementations.
61pub mod clients;
62/// Error structs returned by Redis commands.
63pub mod error;
64/// Traits that implement portions of the Redis interface.
65pub mod interfaces;
66#[cfg(feature = "mocks")]
67#[cfg_attr(docsrs, doc(cfg(feature = "mocks")))]
68pub use modules::mocks;
69/// An interface to run the `MONITOR` command.
70#[cfg(feature = "monitor")]
71#[cfg_attr(docsrs, doc(cfg(feature = "monitor")))]
72pub mod monitor;
73/// The structs and enums used by the Redis client.
74pub mod types;
75
76mod runtime;
77
78/// Various client utility functions.
79pub mod util {
80  pub use crate::utils::{f64_to_string, static_bytes, static_str, string_to_f64};
81  use crate::{error::Error, types::Key};
82  pub use redis_protocol::redis_keyslot;
83  use std::collections::{BTreeMap, VecDeque};
84
85  /// A convenience constant for `None` values used as generic arguments.
86  ///
87  /// Functions that take `Option<T>` as an argument often require the caller to use a turbofish when the
88  /// variant is `None`. In many cases this constant can be used instead.
89  // pretty much everything in this crate supports From<String>
90  pub const NONE: Option<String> = None;
91
92  /// Calculate the SHA1 hash output as a hex string. This is provided for clients that use the Lua interface to
93  /// manage their own script caches.
94  #[cfg(feature = "sha-1")]
95  #[cfg_attr(docsrs, doc(cfg(feature = "sha-1")))]
96  pub fn sha1_hash(input: &str) -> String {
97    use sha1::Digest;
98
99    let mut hasher = sha1::Sha1::new();
100    hasher.update(input.as_bytes());
101    format!("{:x}", hasher.finalize())
102  }
103
104  /// Group the provided arguments by their cluster hash slot.
105  ///
106  /// This can be useful with commands that require all keys map to the same hash slot, such as `SSUBSCRIBE`,
107  /// `MGET`, etc.
108  ///
109  /// ```rust
110  /// # use fred::prelude::*;
111  /// async fn example(client: impl KeysInterface) -> Result<(), Error> {
112  ///   let keys = vec!["foo", "bar", "baz", "a{1}", "b{1}", "c{1}"];
113  ///   let groups = fred::util::group_by_hash_slot(keys)?;
114  ///
115  ///   for (slot, keys) in groups.into_iter() {
116  ///     // `MGET` requires that all arguments map to the same hash slot
117  ///     println!("{:?}", client.mget::<Vec<String>, _>(keys).await?);
118  ///   }
119  ///   Ok(())
120  /// }
121  /// ```
122  pub fn group_by_hash_slot<T>(args: impl IntoIterator<Item = T>) -> Result<BTreeMap<u16, VecDeque<Key>>, Error>
123  where
124    T: TryInto<Key>,
125    T::Error: Into<Error>,
126  {
127    let mut out = BTreeMap::new();
128
129    for arg in args.into_iter() {
130      let arg: Key = to!(arg)?;
131      let slot = redis_keyslot(arg.as_bytes());
132
133      out.entry(slot).or_insert(VecDeque::new()).push_back(arg);
134    }
135    Ok(out)
136  }
137}
138
139/// Convenience module to import a `RedisClient`, all possible interfaces, error types, and common argument types or
140/// return value types.
141pub mod prelude {
142  #[cfg(feature = "dynamic-pool")]
143  #[cfg_attr(docsrs, doc(cfg(feature = "dynamic-pool")))]
144  pub use crate::clients::DynamicPool;
145  #[cfg(feature = "partial-tracing")]
146  #[cfg_attr(docsrs, doc(cfg(feature = "partial-tracing")))]
147  pub use crate::types::config::TracingConfig;
148
149  pub use crate::{
150    clients::{Client, Pool},
151    error::{Error, ErrorKind},
152    interfaces::*,
153    types::{
154      config::{
155        Blocking,
156        Config,
157        ConnectionConfig,
158        Options,
159        PerformanceConfig,
160        ReconnectPolicy,
161        Server,
162        ServerConfig,
163        TcpConfig,
164      },
165      Builder,
166      ClientState,
167      Expiration,
168      FromKey,
169      FromValue,
170      Key,
171      SetOptions,
172      Value,
173      ValueKind,
174    },
175  };
176
177  #[cfg(any(
178    feature = "enable-native-tls",
179    feature = "enable-rustls",
180    feature = "enable-rustls-ring"
181  ))]
182  #[cfg_attr(
183    docsrs,
184    doc(cfg(any(
185      feature = "enable-rustls",
186      feature = "enable-native-tls",
187      feature = "enable-rustls-ring"
188    )))
189  )]
190  pub use crate::types::config::{TlsConfig, TlsConnector};
191}