use crate::network::client::CommandErrors;
use alloc::string::ToString;
use bytes::{Bytes, BytesMut};
use redis_protocol::resp2::types::Frame as Resp2Frame;
use redis_protocol::resp3::prelude::Frame;
use redis_protocol::resp3::types::DecodedFrame;
use redis_protocol::resp3::types::Frame as Resp3Frame;
use redis_protocol::types::RedisProtocolError;
use redis_protocol::{resp2, resp3};
pub trait Protocol: Clone {
type FrameType;
fn decode(&self, data: &Bytes) -> Result<Option<(Self::FrameType, usize)>, RedisProtocolError>;
fn encode_bytes(&self, buf: &mut BytesMut, frame: &Self::FrameType) -> Result<usize, RedisProtocolError>;
fn assert_error(&self, frame: &Self::FrameType) -> Result<(), CommandErrors>;
fn requires_hello(&self) -> bool {
false
}
}
#[derive(Clone, Debug)]
pub struct Resp2 {}
impl Protocol for Resp2 {
type FrameType = Resp2Frame;
fn decode(&self, data: &Bytes) -> Result<Option<(Self::FrameType, usize)>, RedisProtocolError> {
resp2::decode::decode(data)
}
fn encode_bytes(&self, buf: &mut BytesMut, frame: &Self::FrameType) -> Result<usize, RedisProtocolError> {
resp2::encode::encode_bytes(buf, frame)
}
fn assert_error(&self, frame: &Self::FrameType) -> Result<(), CommandErrors> {
match frame {
Resp2Frame::Error(message) => Err(CommandErrors::ErrorResponse(message.to_string())),
_ => Ok(()),
}
}
}
#[derive(Clone, Debug)]
pub struct Resp3 {}
impl Protocol for Resp3 {
type FrameType = Resp3Frame;
fn decode(&self, data: &Bytes) -> Result<Option<(Self::FrameType, usize)>, RedisProtocolError> {
match resp3::decode::streaming::decode(data) {
Ok(option) => match option {
None => Ok(None),
Some(decoded) => {
let (frame, size) = decoded;
match frame {
DecodedFrame::Streaming(_) => Ok(None),
DecodedFrame::Complete(complete_frame) => Ok(Some((complete_frame, size))),
}
}
},
Err(error) => Err(error),
}
}
fn encode_bytes(&self, buf: &mut BytesMut, frame: &Self::FrameType) -> Result<usize, RedisProtocolError> {
resp3::encode::complete::encode_bytes(buf, frame)
}
fn assert_error(&self, frame: &Self::FrameType) -> Result<(), CommandErrors> {
match frame {
Frame::BlobError { .. } => Err(CommandErrors::ErrorResponse("blob".to_string())),
Frame::SimpleError { data, attributes: _ } => Err(CommandErrors::ErrorResponse(data.to_string())),
_ => Ok(()),
}
}
fn requires_hello(&self) -> bool {
true
}
}