embedded_redis/network/
protocol.rs

1use crate::network::client::CommandErrors;
2use alloc::string::ToString;
3use bytes::{Bytes, BytesMut};
4use redis_protocol::error::RedisProtocolError;
5use redis_protocol::resp2::types::BytesFrame as Resp2Frame;
6use redis_protocol::resp3::types::BytesFrame as Resp3Frame;
7use redis_protocol::resp3::types::DecodedFrame;
8use redis_protocol::{resp2, resp3};
9
10/// Generic wrapper for redis-protocol encode/decode methods
11pub trait Protocol: Clone {
12    type FrameType;
13
14    /// Decodes bytes to Frame
15    fn decode(&self, data: &Bytes) -> Result<Option<(Self::FrameType, usize)>, RedisProtocolError>;
16
17    /// Encodes Frame to buffer
18    fn encode_bytes(&self, buf: &mut BytesMut, frame: &Self::FrameType) -> Result<usize, RedisProtocolError>;
19
20    /// Wraps response error to CommandError
21    fn assert_error(&self, frame: &Self::FrameType) -> Result<(), CommandErrors>;
22
23    /// Returns true if protocol switch, respectively HELLO command, is needed
24    fn requires_hello(&self) -> bool {
25        false
26    }
27}
28
29/// Abstraction for RESP2 protocol
30#[derive(Clone, Debug)]
31pub struct Resp2 {}
32
33impl Protocol for Resp2 {
34    type FrameType = Resp2Frame;
35
36    fn decode(&self, data: &Bytes) -> Result<Option<(Self::FrameType, usize)>, RedisProtocolError> {
37        resp2::decode::decode_bytes(data)
38    }
39
40    fn encode_bytes(&self, buf: &mut BytesMut, frame: &Self::FrameType) -> Result<usize, RedisProtocolError> {
41        resp2::encode::encode_bytes(buf, frame, false)
42    }
43
44    fn assert_error(&self, frame: &Self::FrameType) -> Result<(), CommandErrors> {
45        match frame {
46            Resp2Frame::Error(message) => Err(CommandErrors::ErrorResponse(message.to_string())),
47            _ => Ok(()),
48        }
49    }
50}
51
52/// Abstraction for RESP3 protocol
53#[derive(Clone, Debug)]
54pub struct Resp3 {}
55
56impl Protocol for Resp3 {
57    type FrameType = Resp3Frame;
58
59    /// Currently just decodes complete frames
60    /// In case of streaming frame None is returned. In Redis <= 6 there is currently no command
61    /// returning a stream frame.
62    fn decode(&self, data: &Bytes) -> Result<Option<(Self::FrameType, usize)>, RedisProtocolError> {
63        match resp3::decode::streaming::decode_bytes(data) {
64            Ok(option) => match option {
65                None => Ok(None),
66                Some(decoded) => {
67                    let (frame, size) = decoded;
68                    match frame {
69                        DecodedFrame::Streaming(_) => Ok(None),
70                        DecodedFrame::Complete(complete_frame) => Ok(Some((complete_frame, size))),
71                    }
72                }
73            },
74            Err(error) => Err(error),
75        }
76    }
77
78    fn encode_bytes(&self, buf: &mut BytesMut, frame: &Self::FrameType) -> Result<usize, RedisProtocolError> {
79        resp3::encode::complete::encode_bytes(buf, frame, false)
80    }
81
82    fn assert_error(&self, frame: &Self::FrameType) -> Result<(), CommandErrors> {
83        match frame {
84            Resp3Frame::BlobError { .. } => Err(CommandErrors::ErrorResponse("blob".to_string())),
85            Resp3Frame::SimpleError { data, attributes: _ } => {
86                Err(CommandErrors::ErrorResponse(data.to_string()))
87            }
88            _ => Ok(()),
89        }
90    }
91
92    fn requires_hello(&self) -> bool {
93        true
94    }
95}