Skip to main content

ember_protocol/
types.rs

1//! RESP3 frame types.
2//!
3//! The [`Frame`] enum represents a single parsed RESP3 value.
4//! Blob strings use `Bytes` for efficient, reference-counted storage
5//! that avoids unnecessary copies when moving data through the pipeline.
6
7use bytes::Bytes;
8
9/// A single RESP3 protocol frame.
10///
11/// Covers the core types needed for basic Redis-compatible commands:
12/// strings, errors, integers, bulk data, arrays, null, and maps.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Frame {
15    /// Simple string response, e.g. `+OK\r\n`.
16    /// Used for short, non-binary status replies.
17    Simple(String),
18
19    /// Error response, e.g. `-ERR unknown command\r\n`.
20    Error(String),
21
22    /// 64-bit signed integer, e.g. `:42\r\n`.
23    Integer(i64),
24
25    /// Bulk (binary-safe) string, e.g. `$5\r\nhello\r\n`.
26    /// Uses `Bytes` for zero-copy-friendly handling.
27    Bulk(Bytes),
28
29    /// Ordered array of frames, e.g. `*2\r\n+hello\r\n+world\r\n`.
30    Array(Vec<Frame>),
31
32    /// Null value, e.g. `_\r\n`.
33    Null,
34
35    /// Ordered map of key-value frame pairs, e.g. `%1\r\n+key\r\n+val\r\n`.
36    Map(Vec<(Frame, Frame)>),
37}
38
39impl Frame {
40    /// Returns `true` if this frame is a null value.
41    pub fn is_null(&self) -> bool {
42        matches!(self, Frame::Null)
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn frame_equality() {
52        assert_eq!(Frame::Simple("OK".into()), Frame::Simple("OK".into()));
53        assert_ne!(Frame::Simple("OK".into()), Frame::Simple("ERR".into()));
54        assert_eq!(Frame::Integer(42), Frame::Integer(42));
55        assert_eq!(Frame::Null, Frame::Null);
56    }
57
58    #[test]
59    fn is_null() {
60        assert!(Frame::Null.is_null());
61        assert!(!Frame::Simple("OK".into()).is_null());
62        assert!(!Frame::Integer(0).is_null());
63    }
64
65    #[test]
66    fn clone_bulk() {
67        let frame = Frame::Bulk(Bytes::from_static(b"hello"));
68        let cloned = frame.clone();
69        assert_eq!(frame, cloned);
70    }
71}