| Crates.io | rediserde |
| lib.rs | rediserde |
| version | 0.2.0 |
| created_at | 2025-07-29 13:44:25.143626+00 |
| updated_at | 2025-08-12 15:38:59.480418+00 |
| description | RESP (Redis Serialization Protocol) for Serde |
| homepage | |
| repository | https://github.com/ofersadan85/rediserde |
| max_upload_size | |
| id | 1772370 |
| size | 120,968 |
A Serde implementation for the RESP (Redis Serialization Protocol) format, supporting both serialization and deserialization of Rust data structures.
to_string, to_bytes, from_str, from_bytescargo add serde --features derive
cargo add rediserde
Or add to your Cargo.toml:
[dependencies]
rediserde = "0.1.0"
serde = { version = "1.0", features = ["derive"] }
[!NOTE]
derivefeature is optional but recommended for ease of use (with#[derive(Serialize, Deserialize)])
Use this crate like any other serde-compatible crate (like serde_json or serde_yaml):
use rediserde::{from_str, to_string};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Person {
name: String,
age: u32,
}
let person = Person {
name: "Alice".to_string(),
age: 30,
};
let serialized = to_string(&person).unwrap();
let deserialized: Person = from_str(&serialized).unwrap();
let deserialized_raw: Person = from_str("%2\r\n+name\r\n+Alice\r\n+age\r\n:30\r\n").unwrap();
assert_eq!(deserialized, person);
assert_eq!(deserialized_raw, person);
For a more complex example, see the tests/structs.rs file.
For more details on how to use this crate, refer to the Serde documentation.
This crate supports the full RESP2 + RESP3 protocol specification, including:
However, to match with Rust's (and serde's) types the mapping is roughly as follows:
| RESP Type | Rust Type |
|---|---|
| Simple String | String |
| Error | String |
| Integer | u8-u32, i8-i64 |
| Bulk String | String |
| Array | Vec<T> |
| Null | Option<T> (None) |
| Boolean | bool |
| Double | f64 |
| Big Number | u64 & usize |
| Verbatim String | String |
| Map | HashMap<String, T> |
| Attribute | HashMap<String, T> |
| Set | Vec<T> |
| Push | Vec<T> |
However, since the mapping is not one-to-one, there are some important notes:
Integers are deserializable to any Rust integer numeric type, assuming they fit within the range of the target type.Big Numbers are deserializable to all "smaller" Rust integer types assuming they fit within the range of the target type, but RESP Integer is at most i64, so a Rust u64 (which might be bigger) will always be serialized as a Big Number while other numeric integer types will be serialized as RESP Integers.Doubles (floating point numbers) are deserializable to both f64 and f32, assuming they fit within the range of the target type.Maps and Attributes are both deserializable into structs, and HashMaps but structs and HashMaps are always serialized as RESP Maps.Arrays, Sets, and Pushes are deserializable into any Rust sequence type (like Vec, HashSet, etc.) but Rust sequences are always serialized as RESP Arrays.Simple String, Simple Error, Bulk String, Bulk Error, Verbatim String) are deserializable into a Rust String, but Rust Strings are always serialized as RESP Bulk String (as this is the most common and versatile string type in RESP).Strings are guaranteed to be UTF-8 encoded, but RESP types are not, so deserializing will fail if the RESP data is not valid UTF-8. If you're unsure, deserialize to bytes (Vec<u8>) instead and handle the data manually.u128 and i128 are not supported by serde. If support is added there, we will follow and they will have to be serialized as RESP Big Numbers.Null type, so creating a RESP Null is only possible in the context of an Option<T> where T is any type. The None variant will be serialized as RESP Null and vice versa.HashMap<String, T> or Vec<T> with mixed types will fail.Strings are supported as map keys (although RESP supports any type). This is planned to be extended in the future to support more types, but only as far as is reasonable for Rust, i.e. types that implement the Hash and Eq traits as required by HashMap.To try and minimize dependencies and maximize flexibility in further development, this crate does not depend on any of the above crates, but rather implements RESP serialization and deserialization directly.