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
/*!
Defines types related to the [`RESP`](https://redis.io/docs/reference/protocol-spec/) protocol and their encoding/decoding
# Object Model
**rustis** provides an object model in the form of a generic data struct, comparable to the XML DOM,
and which matches perfectly the RESP protocol: the enum [`resp::Value`](Value).
Each variant of this enum matches a [`RESP`](https://redis.io/docs/reference/protocol-spec/) type.
Because, navigating through a [`resp::Value`](Value) instance can be verbose and requires a lot of pattern matching,
**rustis** provides a [`resp::Value`](Value) to Rust type conversion with a [serde](https://serde.rs/)
deserializer implementation of a [`resp::Value`](Value) reference.
This conversion is easily accessible through the associate function [`Value::into`](Value::into).
# Command arguments
**rustis** provides an idiomatic way to pass arguments to [commands](crate::commands).
Basically a [`Command`] is a built through a builder which accepts a command name and one ore more command arguments.
The only requirement for the command argument is that they must implement the serde [`Serialize`] trait.
It gives to **rustis** a great flexibility to accept many type of arguments for the same command.
#### Example
```
use rustis::{
client::Client,
commands::{FlushingMode, ServerCommands, StringCommands},
Result,
};
use serde::Serialize;
#[derive(Serialize)]
pub struct MyI32(i32);
#[cfg_attr(feature = "tokio-runtime", tokio::main)]
#[cfg_attr(feature = "async-std-runtime", async_std::main)]
async fn main() -> Result<()> {
// Connect the client to a Redis server from its IP and port
let client = Client::connect("127.0.0.1:6379").await?;
// Flush all existing data in Redis
client.flushdb(FlushingMode::Sync).await?;
client.set("key", 12).await?;
client.set("key", 12i64).await?;
client.set("key", 12.12).await?;
client.set("key", true).await?;
client.set("key", "value").await?;
client.set("key", "value".to_owned()).await?;
client.set("key", 'c').await?;
client.set("key", MyI32(12)).await?;
Ok(())
}
```
## Byte arguments and serde limitations
Due to how serde handles byte types, passing raw byte values like `&[u8]`,
`Vec<u8>`, or byte literals like `b"val"` directly as command arguments
will **not** produce a single RESP bulk string. Instead, serde serializes
them as sequences of individual integer values, resulting in a runtime error.
This is a fundamental serde limitation: without specialization, there is no
way to distinguish a `&[u8]` from any other `&[T]` at the trait level.
Note that `&str` works correctly because it is a distinct type, not a slice.
To pass raw bytes as a single bulk string argument, use the provided adapter types:
- [`BulkString`] for owned byte data (`Vec<u8>`) — moves ownership, zero allocation
- [`RefBulkString`] for borrowed byte data (`&[u8]`) — zero allocation
#### Example
```
use rustis::{
client::Client,
commands::StringCommands,
resp::{BulkString, RefBulkString},
Result,
};
#[cfg_attr(feature = "tokio-runtime", tokio::main)]
#[cfg_attr(feature = "async-std-runtime", async_std::main)]
async fn main() -> Result<()> {
let client = Client::connect("127.0.0.1:6379").await?;
// &[u8]: use RefBulkString (zero allocation, borrowed)
client.set("key", RefBulkString::new(b"val")).await?;
// Vec<u8>: use BulkString (zero allocation, owned)
client.set("key", BulkString::new(b"val".to_vec())).await?;
Ok(())
}
```
# Command results
**rustis** provides an idiomatic way to convert command results into Rust types with the help of [serde](serde.rs)
You will notice that each built-in command returns a [`PreparedCommand<R>`](crate::client::PreparedCommand)
struct where `R` represents the [`Response`] of the command.
The different command traits implementations ([`Client`](crate::client::Client), [`Pipeline`](crate::client::Pipeline)
or [`Transaction`](crate::client::Transaction)) add a constraint on the reponse `R`:
it must implement serde [`Deserialize`](https://docs.rs/serde/latest/serde/trait.Deserialize.html) trait.
Indeed, **rustis** provides a serde implementation of a [`RESP deserializer`](RespDeserializer).
Each custom struct or enum defined as a response of a built-command implements
serde [`Deserialize`](https://docs.rs/serde/latest/serde/trait.Deserialize.html) trait,
in order to deserialize it automatically from a RESP Buffer.
*/
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;
pub use *;