1#[derive(Debug, Clone, PartialEq)]
5pub enum RedisValue {
6 Nil,
8 Int(i64),
10 Float(f64),
12 String(String),
14 Bytes(Vec<u8>),
16 Array(Vec<RedisValue>),
18 Bool(bool),
20}
21
22impl RedisValue {
23 pub fn as_string(&self) -> Option<String> {
40 match self {
41 RedisValue::String(s) => Some(s.clone()),
42 _ => None,
43 }
44 }
45
46 pub fn as_i64(&self) -> Option<i64> {
52 match self {
53 RedisValue::Int(i) => Some(*i),
54 _ => None,
55 }
56 }
57
58 pub fn as_f64(&self) -> Option<f64> {
64 match self {
65 RedisValue::Float(f) => Some(*f),
66 _ => None,
67 }
68 }
69
70 pub fn as_bool(&self) -> Option<bool> {
76 match self {
77 RedisValue::Bool(b) => Some(*b),
78 _ => None,
79 }
80 }
81
82 pub fn as_bytes(&self) -> Option<&[u8]> {
88 match self {
89 RedisValue::Bytes(b) => Some(b.as_slice()),
90 _ => None,
91 }
92 }
93
94 pub fn as_array(&self) -> Option<&[RedisValue]> {
100 match self {
101 RedisValue::Array(arr) => Some(arr.as_slice()),
102 _ => None,
103 }
104 }
105
106 pub fn is_nil(&self) -> bool {
112 matches!(self, RedisValue::Nil)
113 }
114}
115
116impl From<String> for RedisValue {
118 fn from(s: String) -> Self {
119 RedisValue::String(s)
120 }
121}
122
123impl From<&str> for RedisValue {
124 fn from(s: &str) -> Self {
125 RedisValue::String(s.to_string())
126 }
127}
128
129impl From<i64> for RedisValue {
130 fn from(i: i64) -> Self {
131 RedisValue::Int(i)
132 }
133}
134
135impl From<i32> for RedisValue {
136 fn from(i: i32) -> Self {
137 RedisValue::Int(i as i64)
138 }
139}
140
141impl From<f64> for RedisValue {
142 fn from(f: f64) -> Self {
143 RedisValue::Float(f)
144 }
145}
146
147impl From<bool> for RedisValue {
148 fn from(b: bool) -> Self {
149 RedisValue::Bool(b)
150 }
151}
152
153impl From<Vec<u8>> for RedisValue {
154 fn from(bytes: Vec<u8>) -> Self {
155 RedisValue::Bytes(bytes)
156 }
157}
158
159impl From<redis::Value> for RedisValue {
161 fn from(value: redis::Value) -> Self {
162 match value {
163 redis::Value::Nil => RedisValue::Nil,
164 redis::Value::Int(i) => RedisValue::Int(i),
165 redis::Value::BulkString(bytes) => {
166 match String::from_utf8(bytes.clone()) {
168 Ok(s) => RedisValue::String(s),
169 Err(_) => RedisValue::Bytes(bytes),
170 }
171 }
172 redis::Value::Array(values) => {
173 RedisValue::Array(values.into_iter().map(RedisValue::from).collect())
174 }
175 redis::Value::SimpleString(s) => RedisValue::String(s),
176 redis::Value::Okay => RedisValue::Bool(true),
177 redis::Value::Map(_) => {
178 RedisValue::String(format!("{:?}", value))
180 }
181 redis::Value::Attribute { .. } => {
182 RedisValue::String(format!("{:?}", value))
184 }
185 redis::Value::Set(_) => {
186 RedisValue::String(format!("{:?}", value))
188 }
189 redis::Value::Double(f) => RedisValue::Float(f),
190 redis::Value::Boolean(b) => RedisValue::Bool(b),
191 redis::Value::VerbatimString { .. } => {
192 RedisValue::String(format!("{:?}", value))
194 }
195 redis::Value::BigNumber(_) => {
196 RedisValue::String(format!("{:?}", value))
198 }
199 redis::Value::Push { .. } => {
200 RedisValue::String(format!("{:?}", value))
202 }
203 _ => RedisValue::String(format!("{:?}", value)),
205 }
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn test_redis_value_nil() {
215 let value = RedisValue::Nil;
216 assert!(value.is_nil());
217 assert_eq!(value.as_string(), None);
218 assert_eq!(value.as_i64(), None);
219 }
220
221 #[test]
222 fn test_redis_value_int() {
223 let value = RedisValue::Int(42);
224 assert!(!value.is_nil());
225 assert_eq!(value.as_i64(), Some(42));
226 assert_eq!(value.as_string(), None);
227 }
228
229 #[test]
230 fn test_redis_value_float() {
231 let value = RedisValue::Float(123.456);
232 assert_eq!(value.as_f64(), Some(123.456));
233 assert_eq!(value.as_i64(), None);
234 }
235
236 #[test]
237 fn test_redis_value_string() {
238 let value = RedisValue::String("hello".to_string());
239 assert_eq!(value.as_string(), Some("hello".to_string()));
240 assert_eq!(value.as_i64(), None);
241 }
242
243 #[test]
244 fn test_redis_value_bool() {
245 let value = RedisValue::Bool(true);
246 assert_eq!(value.as_bool(), Some(true));
247 assert_eq!(value.as_string(), None);
248 }
249
250 #[test]
251 fn test_redis_value_bytes() {
252 let bytes = vec![1, 2, 3, 4];
253 let value = RedisValue::Bytes(bytes.clone());
254 assert_eq!(value.as_bytes(), Some(bytes.as_slice()));
255 assert_eq!(value.as_string(), None);
256 }
257
258 #[test]
259 fn test_redis_value_array() {
260 let arr = vec![
261 RedisValue::Int(1),
262 RedisValue::String("test".to_string()),
263 RedisValue::Nil,
264 ];
265 let value = RedisValue::Array(arr.clone());
266 assert_eq!(value.as_array(), Some(arr.as_slice()));
267 assert_eq!(value.as_string(), None);
268 }
269
270 #[test]
271 fn test_from_string() {
272 let value: RedisValue = "hello".into();
273 assert_eq!(value, RedisValue::String("hello".to_string()));
274
275 let value: RedisValue = String::from("world").into();
276 assert_eq!(value, RedisValue::String("world".to_string()));
277 }
278
279 #[test]
280 fn test_from_int() {
281 let value: RedisValue = 42i64.into();
282 assert_eq!(value, RedisValue::Int(42));
283
284 let value: RedisValue = 100i32.into();
285 assert_eq!(value, RedisValue::Int(100));
286 }
287
288 #[test]
289 fn test_from_float() {
290 let value: RedisValue = 123.456f64.into();
291 assert_eq!(value, RedisValue::Float(123.456));
292 }
293
294 #[test]
295 fn test_from_bool() {
296 let value: RedisValue = true.into();
297 assert_eq!(value, RedisValue::Bool(true));
298
299 let value: RedisValue = false.into();
300 assert_eq!(value, RedisValue::Bool(false));
301 }
302
303 #[test]
304 fn test_from_bytes() {
305 let bytes = vec![1, 2, 3];
306 let value: RedisValue = bytes.clone().into();
307 assert_eq!(value, RedisValue::Bytes(bytes));
308 }
309
310 #[test]
311 fn test_from_redis_value_nil() {
312 let redis_val = redis::Value::Nil;
313 let value: RedisValue = redis_val.into();
314 assert_eq!(value, RedisValue::Nil);
315 }
316
317 #[test]
318 fn test_from_redis_value_int() {
319 let redis_val = redis::Value::Int(42);
320 let value: RedisValue = redis_val.into();
321 assert_eq!(value, RedisValue::Int(42));
322 }
323
324 #[test]
325 fn test_from_redis_value_data_utf8() {
326 let redis_val = redis::Value::BulkString(b"hello".to_vec());
327 let value: RedisValue = redis_val.into();
328 assert_eq!(value, RedisValue::String("hello".to_string()));
329 }
330
331 #[test]
332 fn test_from_redis_value_data_binary() {
333 let bytes = vec![0xFF, 0xFE, 0xFD];
334 let redis_val = redis::Value::BulkString(bytes.clone());
335 let value: RedisValue = redis_val.into();
336 assert_eq!(value, RedisValue::Bytes(bytes));
337 }
338
339 #[test]
340 fn test_from_redis_value_bulk() {
341 let redis_val = redis::Value::Array(vec![
342 redis::Value::Int(1),
343 redis::Value::BulkString(b"test".to_vec()),
344 ]);
345 let value: RedisValue = redis_val.into();
346
347 if let RedisValue::Array(arr) = value {
348 assert_eq!(arr.len(), 2);
349 assert_eq!(arr[0], RedisValue::Int(1));
350 assert_eq!(arr[1], RedisValue::String("test".to_string()));
351 } else {
352 panic!("Expected Array");
353 }
354 }
355
356 #[test]
357 fn test_from_redis_value_status() {
358 let redis_val = redis::Value::SimpleString("OK".to_string());
359 let value: RedisValue = redis_val.into();
360 assert_eq!(value, RedisValue::String("OK".to_string()));
361 }
362
363 #[test]
364 fn test_from_redis_value_okay() {
365 let redis_val = redis::Value::Okay;
366 let value: RedisValue = redis_val.into();
367 assert_eq!(value, RedisValue::Bool(true));
368 }
369
370 #[test]
371 fn test_clone() {
372 let value = RedisValue::String("test".to_string());
373 let cloned = value.clone();
374 assert_eq!(value, cloned);
375 }
376
377 #[test]
378 fn test_debug() {
379 let value = RedisValue::Int(42);
380 let debug_str = format!("{:?}", value);
381 assert!(debug_str.contains("Int"));
382 assert!(debug_str.contains("42"));
383 }
384
385 #[test]
386 fn test_partial_eq() {
387 assert_eq!(RedisValue::Nil, RedisValue::Nil);
388 assert_eq!(RedisValue::Int(42), RedisValue::Int(42));
389 assert_ne!(RedisValue::Int(42), RedisValue::Int(43));
390 assert_ne!(RedisValue::Int(42), RedisValue::String("42".to_string()));
391 }
392}