1use crate::RespPrimitive;
2use bytes::Bytes;
3use ordered_float::OrderedFloat;
4use std::collections::{BTreeMap, BTreeSet};
5
6#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
11pub enum RespValue {
12 Attribute(BTreeMap<RespPrimitive, RespValue>),
13 Array(Vec<RespValue>),
14 Bignum(Bytes),
15 Boolean(bool),
16 Double(OrderedFloat<f64>),
17 Error(Bytes),
18 Integer(i64),
19 Map(BTreeMap<RespPrimitive, RespValue>),
20 Nil,
21 Push(Vec<RespValue>),
22 Set(BTreeSet<RespPrimitive>),
23 String(Bytes),
24 Verbatim(Bytes, Bytes),
25}
26
27impl From<bool> for RespValue {
28 fn from(value: bool) -> Self {
29 RespValue::Boolean(value)
30 }
31}
32
33impl From<i32> for RespValue {
34 fn from(value: i32) -> Self {
35 RespValue::Integer(value.into())
36 }
37}
38
39impl From<i64> for RespValue {
40 fn from(value: i64) -> Self {
41 RespValue::Integer(value)
42 }
43}
44
45impl From<f64> for RespValue {
46 fn from(value: f64) -> Self {
47 RespValue::Double(value.into())
48 }
49}
50
51impl From<String> for RespValue {
52 fn from(value: String) -> Self {
53 RespValue::String(value.into())
54 }
55}
56
57impl From<&'static str> for RespValue {
58 fn from(value: &'static str) -> Self {
59 RespValue::String(value.into())
60 }
61}
62
63impl<const N: usize> From<&'static [u8; N]> for RespValue {
64 fn from(value: &'static [u8; N]) -> Self {
65 RespValue::String((&value[..]).into())
66 }
67}
68
69impl From<Vec<u8>> for RespValue {
70 fn from(value: Vec<u8>) -> Self {
71 RespValue::String(value.into())
72 }
73}
74
75impl RespValue {
76 pub fn array(&mut self) -> Option<&mut Vec<RespValue>> {
78 if let RespValue::Array(value) = self {
79 Some(value)
80 } else {
81 None
82 }
83 }
84
85 pub fn error(&self) -> Option<&str> {
87 if let RespValue::Error(value) = self {
88 std::str::from_utf8(value).ok()
89 } else {
90 None
91 }
92 }
93
94 pub fn integer(&self) -> Option<i64> {
96 if let RespValue::Integer(i) = self {
97 Some(*i)
98 } else {
99 None
100 }
101 }
102
103 pub fn text(&self) -> Option<&str> {
105 use RespValue::*;
106
107 if let String(text) | Verbatim(_, text) = self {
108 std::str::from_utf8(text).ok()
109 } else {
110 None
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn array() {
121 assert_eq!(RespValue::Array(vec![]), resp! { [] });
122 assert_eq!(
123 RespValue::Array(vec![RespValue::Array(vec![])]),
124 resp! { [[]] }
125 );
126 assert_eq!(RespValue::Array(vec![RespValue::Nil]), resp! { [nil] });
127 assert_eq!(RespValue::Array(vec![1i64.into()]), resp! { [1i64] });
128 assert_eq!(
129 RespValue::Array(vec![1i64.into(), 2i64.into()]),
130 resp! { [1i64, 2i64] }
131 );
132 }
133
134 #[test]
135 fn bignum() {
136 assert_eq!(RespValue::Bignum("1234".into()), resp! { (big "1234") });
137 assert_eq!(
138 RespValue::Array(vec![RespValue::Bignum("1234".into())]),
139 resp! { [(big "1234")] }
140 );
141 }
142
143 #[test]
144 fn boolean() {
145 assert_eq!(RespValue::Boolean(true), resp! { true });
146 assert_eq!(RespValue::Boolean(false), resp! { false });
147 assert_eq!(
148 RespValue::Array(vec![true.into(), false.into()]),
149 resp! { [true, false] }
150 );
151 }
152
153 #[test]
154 fn string() {
155 assert_eq!(RespValue::String("1234".into()), resp! { "1234" });
156 }
157
158 #[test]
159 fn double() {
160 assert_eq!(RespValue::Double(1f64.into()), resp! { 1f64 });
161 }
162
163 #[test]
164 fn integer() {
165 assert_eq!(RespValue::Integer(1i64), resp! { 1i64 });
166 assert_eq!(RespValue::Integer(-1i64), resp! { (-1) });
167 }
168
169 #[test]
170 fn map() {
171 #[allow(clippy::mutable_key_type)]
174 let mut map = BTreeMap::new();
175 map.insert("x".into(), "1".into());
176 map.insert(1i64.into(), 1f64.into());
177 map.insert(RespPrimitive::Nil, RespValue::Nil);
178 assert_eq!(
179 RespValue::Map(map),
180 resp! { {"x" => "1", 1i64 => 1f64, nil => nil} }
181 );
182 }
183
184 #[test]
185 fn nil() {
186 assert_eq!(RespValue::Nil, resp! { nil });
187 }
188
189 #[test]
190 fn push() {
191 assert_eq!(RespValue::Push(vec![]), resp! { [>] });
192 assert_eq!(RespValue::Push(vec![RespValue::Nil]), resp! { [> nil] });
193 assert_eq!(RespValue::Push(vec![1i64.into()]), resp! { [> 1i64] });
194 }
195
196 #[test]
197 fn set() {
198 #[allow(clippy::mutable_key_type)]
201 let mut set = BTreeSet::new();
202 set.insert("x".into());
203 set.insert("y".into());
204 set.insert(RespPrimitive::Nil);
205 assert_eq!(RespValue::Set(set), resp! { {"x", "y", nil} });
206 }
207
208 #[test]
209 fn verbatim() {
210 assert_eq!(
211 RespValue::Verbatim("txt".into(), "abc".into()),
212 resp! { (= "txt", "abc") }
213 );
214 }
215
216 #[test]
217 fn error() {
218 assert_eq!(
219 RespValue::Error("ERR stuff".into()),
220 resp! { (! "ERR stuff") }
221 );
222 }
223
224 #[test]
225 fn text_values() {
226 let value = RespValue::Verbatim("txt".into(), "abc".into());
227 assert_eq!(value.text(), Some("abc"));
228
229 let value = RespValue::String("abc".into());
230 assert_eq!(value.text(), Some("abc"));
231
232 let value = RespValue::Nil;
233 assert_eq!(value.text(), None);
234
235 let value = RespValue::Integer(23);
236 assert_eq!(value.text(), None);
237 }
238
239 #[test]
240 fn error_values() {
241 let value = RespValue::Verbatim("txt".into(), "abc".into());
242 assert_eq!(value.error(), None);
243
244 let value = RespValue::String("abc".into());
245 assert_eq!(value.error(), None);
246
247 let value = RespValue::Nil;
248 assert_eq!(value.error(), None);
249
250 let value = RespValue::Integer(23);
251 assert_eq!(value.error(), None);
252
253 let value = RespValue::Error("error".into());
254 assert_eq!(value.error(), Some("error"));
255 }
256
257 #[test]
258 fn integer_values() {
259 let value = RespValue::Verbatim("txt".into(), "abc".into());
260 assert_eq!(value.integer(), None);
261
262 let value = RespValue::String("abc".into());
263 assert_eq!(value.integer(), None);
264
265 let value = RespValue::Nil;
266 assert_eq!(value.integer(), None);
267
268 let value = RespValue::Integer(23);
269 assert_eq!(value.integer(), Some(23));
270
271 let value = RespValue::Error("error".into());
272 assert_eq!(value.integer(), None);
273 }
274
275 #[test]
276 fn array_values() {
277 let mut value = RespValue::Verbatim("txt".into(), "abc".into());
278 assert_eq!(value.array(), None);
279
280 let mut value = RespValue::String("abc".into());
281 assert_eq!(value.array(), None);
282
283 let mut value = RespValue::Nil;
284 assert_eq!(value.array(), None);
285
286 let mut value = RespValue::Integer(23);
287 assert_eq!(value.array(), None);
288
289 let mut value = RespValue::Error("error".into());
290 assert_eq!(value.array(), None);
291
292 let mut value = RespValue::Array(vec![RespValue::Integer(1), RespValue::Integer(2)]);
293 assert_eq!(
294 value.array(),
295 Some(&mut vec![RespValue::Integer(1), RespValue::Integer(2)])
296 );
297 }
298}