1use bytes::Bytes;
2use std::convert::Infallible;
3
4use crate::resp::Value;
5
6pub type Response = Value;
8
9#[derive(Debug, Clone, Eq, PartialEq)]
11pub enum RespError {
12 InvalidData(Bytes),
14 NoAuth,
16 Internal,
18}
19
20impl RespError {
21 pub fn invalid_data(msg: impl Into<Bytes>) -> Self {
23 let msg = msg.into();
24 if msg.starts_with(b"ERR ") {
25 RespError::InvalidData(msg)
26 } else {
27 let mut buf = Vec::with_capacity(4 + msg.len());
28 buf.extend_from_slice(b"ERR ");
29 buf.extend_from_slice(&msg);
30 RespError::InvalidData(Bytes::from(buf))
31 }
32 }
33
34 pub fn internal() -> Self {
36 RespError::Internal
37 }
38}
39
40pub trait IntoResponse {
42 fn into_response(self) -> Response;
43}
44
45impl IntoResponse for Response {
46 fn into_response(self) -> Response {
47 self
48 }
49}
50
51impl IntoResponse for RespError {
52 fn into_response(self) -> Response {
53 match self {
54 RespError::InvalidData(msg) => Value::Error(msg),
55 RespError::NoAuth => {
56 Value::Error(Bytes::from_static(b"NOAUTH Authentication required."))
57 }
58 RespError::Internal => Value::Error(Bytes::from_static(b"ERR internal error")),
59 }
60 }
61}
62
63impl<T> IntoResponse for Result<T, RespError>
64where
65 T: IntoResponse,
66{
67 fn into_response(self) -> Response {
68 match self {
69 Ok(value) => value.into_response(),
70 Err(err) => err.into_response(),
71 }
72 }
73}
74
75impl IntoResponse for Bytes {
76 fn into_response(self) -> Response {
77 Value::Bulk(self)
78 }
79}
80
81impl IntoResponse for Vec<u8> {
82 fn into_response(self) -> Response {
83 Value::Bulk(Bytes::from(self))
84 }
85}
86
87impl IntoResponse for &'static [u8] {
88 fn into_response(self) -> Response {
89 Value::Bulk(Bytes::from_static(self))
90 }
91}
92
93impl IntoResponse for &'static str {
94 fn into_response(self) -> Response {
95 Value::Bulk(Bytes::from_static(self.as_bytes()))
96 }
97}
98
99impl IntoResponse for String {
100 fn into_response(self) -> Response {
101 Value::Bulk(Bytes::from(self.into_bytes()))
102 }
103}
104
105impl IntoResponse for Infallible {
106 fn into_response(self) -> Response {
107 match self {}
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn invalid_data_prefixes_err() {
117 let err = RespError::invalid_data("oops");
118 if let RespError::InvalidData(msg) = err {
119 assert!(msg.starts_with(b"ERR "));
120 } else {
121 panic!("expected InvalidData");
122 }
123 }
124
125 #[test]
126 fn result_into_response() {
127 let ok: Result<Response, RespError> = Ok(Value::Integer(1));
128 assert_eq!(ok.into_response(), Value::Integer(1));
129 let err: Result<Response, RespError> = Err(RespError::Internal);
130 assert_eq!(
131 err.into_response(),
132 Value::Error(Bytes::from_static(b"ERR internal error"))
133 );
134 }
135}