Skip to main content

kevy_resp/
lib.rs

1//! kevy-resp — a zero-dependency [RESP] (REdis Serialization Protocol) codec.
2//!
3//! It covers what a client sends to drive commands — the RESP2 multi-bulk
4//! request (`*N\r\n$len\r\n…`) and the inline form (a bare `PING\r\n` typed over
5//! a raw connection) — plus the reply primitives a server writes back. Parsing
6//! is incremental and allocation-light: [`parse_command`] returns `Ok(None)`
7//! when more bytes are needed, so it composes with a streaming read loop.
8//!
9//! Pure Rust, no dependencies. Part of the [kevy] key–value server.
10//!
11//! [RESP]: https://redis.io/docs/latest/develop/reference/protocol-spec/
12//! [kevy]: https://crates.io/crates/kevy
13//!
14//! # Example
15//!
16//! ```
17//! use kevy_resp::{encode_bulk, encode_simple_string, parse_command};
18//!
19//! // Parse one command from a request buffer.
20//! let (cmd, consumed) = parse_command(b"*2\r\n$4\r\nECHO\r\n$2\r\nhi\r\n")
21//!     .unwrap() // not a protocol error
22//!     .unwrap(); // a complete frame was present
23//! assert_eq!(cmd, vec![b"ECHO".to_vec(), b"hi".to_vec()]);
24//! assert_eq!(consumed, 22);
25//!
26//! // A partial frame asks for more bytes rather than erroring.
27//! assert_eq!(parse_command(b"*1\r\n$4\r\nPI").unwrap(), None);
28//!
29//! // Encode replies into a caller-owned buffer.
30//! let mut out = Vec::new();
31//! encode_simple_string(&mut out, "PONG");
32//! encode_bulk(&mut out, b"hi");
33//! assert_eq!(out, b"+PONG\r\n$2\r\nhi\r\n");
34//! ```
35#![forbid(unsafe_code)]
36#![warn(missing_docs)]
37
38mod argv;
39mod argv_borrowed;
40mod argv_pool;
41mod argv_view;
42mod error;
43mod reply_encode;
44mod reply_encode_resp3;
45mod reply_parse;
46mod request;
47mod request_borrowed;
48
49pub use argv::{Argv, Command};
50pub use argv_borrowed::ArgvBorrowed;
51pub use argv_pool::ArgvPool;
52pub use argv_view::{ArgvIter, ArgvView};
53pub use error::ProtocolError;
54pub use reply_encode::{
55    encode_array_len, encode_bulk, encode_command, encode_error, encode_integer, encode_null_bulk,
56    encode_simple_string,
57};
58pub use reply_encode_resp3::{
59    encode_big_number, encode_blob_error, encode_boolean, encode_double, encode_map_header,
60    encode_null, encode_push_header, encode_set_header, encode_verbatim,
61};
62pub use reply_parse::{Reply, parse_reply};
63pub use request::{parse_command, parse_command_into};
64pub use request_borrowed::parse_command_borrowed;
65
66/// Which version of RESP a connection is speaking. Negotiated via the
67/// `HELLO` command — RESP2 is the default for backwards compatibility
68/// with every Redis 6.x and earlier client; RESP3 is opt-in via
69/// `HELLO 3` and unlocks the additive reply types
70/// ([`Reply::Map`] / [`Reply::Set`] / [`Reply::Double`] / [`Reply::Boolean`]
71/// / [`Reply::Verbatim`] / [`Reply::BigNumber`] / [`Reply::Null`] /
72/// [`Reply::Push`] / [`Reply::BlobError`]) plus out-of-band push frames
73/// for `PUBLISH` delivery.
74///
75/// Stored per-connection in `kevy-rt` and forwarded to dispatch so each
76/// reply encoder can pick the right wire shape — see the kevy v2 RESP3
77/// design notes for the full phase plan.
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
79pub enum RespVersion {
80    /// RESP2 — every reply is one of the seven legacy prefixes
81    /// (`+ - : $ * $-1 *-1`). Default for backward compatibility.
82    #[default]
83    V2,
84    /// RESP3 — adds 9 reply prefixes (`% ~ , # = ( _ > !`) plus
85    /// attributes (`|`). Opt-in via `HELLO 3`.
86    V3,
87}