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
//! A simple Redis client & RESP parser for Rust.
//!
//! ```
//! use redust::{resp::{Data, from_data}, Connection};
//! # use redust::Error;
//!
//! # tokio_test::block_on(async {
//! let mut conn = Connection::new("localhost:6379").await?;
//! let res: Data = conn.cmd(["PING"]).await?;
//!
//! let deserialized: &str = from_data(res)?;
//! assert_eq!(deserialized, "PONG");
//! # Ok::<_, Error>(())
//! # });
//! ```
//!
//! [`Connection`]s implement [`TryStream`](futures::TryStream) and [`Sink`](futures::Sink) for ergonomic
//! and idiomatic use.
//!
//! Data is returned to the client as static [`resp::Data`]. The [resp] crate contains several
//! [serde] utilities for converting RESP into Rust structures. For reading data from a connection,
//! use [`resp::from_data`].
//!
//! # Additional Features
//!
//! - [`command`]: type-safe Redis interactions
//! - [`pool`]: connection pooling with [bb8]
//! - [`model`]: complex Redis responses, based on [serde]
//! - [`script`]: Redis scripting utilities
/// [`Command`](crate::command::Command) trait + impelementations.
///
/// Enables sending and receiving data to and from Redis using type-safe methods.
///
/// ```rust
/// use redust::{command::connection::Hello, Connection};
/// # use redust::Error;
///
/// # tokio_test::block_on(async {
/// let mut conn = Connection::new("localhost:6379").await?;
/// conn.run(Hello {
/// username: Some("foo"),
/// password: Some("bar"),
/// }).await?;
/// # Ok::<_, Error>(())
/// # });
/// ```
/// Redis models.
/// Manage Redis connections with [deadpool].
///
/// ```rust
/// use redust::pool::{Pool, Manager};
///
/// # tokio_test::block_on(async {
/// let manager = Manager::new("localhost:6379");
/// let pool = Pool::builder(manager).build().expect("pool should be built");
/// # });
/// ```
/// Script utilities to handle SHA1 hash-based invocation.
///
/// ```rust
/// use redust::{resp::Data, script::Script, Connection};
/// # use redust::Error;
/// use lazy_static::lazy_static;
///
/// lazy_static! {
/// static ref MY_SCRIPT: Script =
/// Script::new(b"return 'Hello ' .. redis.call('GET', KEYS[1]) .. ARGV[1]");
/// }
///
/// # tokio_test::block_on(async {
/// let mut conn = Connection::new("localhost:6379").await?;
/// conn.cmd(["SET", "hello", "world"]).await?;
///
/// let res: Data = MY_SCRIPT
/// .exec(&mut conn)
/// .args(["!"])
/// .keys(["hello"])
/// .invoke()
/// .await?;
///
/// assert_eq!(res, b"Hello world!");
/// # Ok::<_, Error>(())
/// # });
/// ```
pub use redust_resp as resp;
pub use ;
pub use Codec;
/// Static [`resp::Error`] returned from [`Connection`] and [`Codec`].
pub type Error = Error;
/// Result with an error type defaulting to [`Error`].
pub type Result<T, E = Error> = Result;