1use crate::core::{
42 error::{RedisError, RedisResult},
43 value::RespValue,
44};
45use bytes::{Buf, BufMut, Bytes, BytesMut};
46use std::collections::{HashMap, HashSet};
47use std::io::Cursor;
48
49#[derive(Debug, Clone, PartialEq)]
51pub enum Resp3Value {
52 SimpleString(String),
54 SimpleError(String),
56 Number(i64),
58 BlobString(String),
60 Array(Vec<Resp3Value>),
62 Null,
64 Boolean(bool),
66 Double(f64),
68 BigNumber(String),
70 BlobError(String),
72 VerbatimString {
74 encoding: String,
76 data: String,
78 },
79 Map(HashMap<String, Resp3Value>),
81 Set(HashSet<Resp3Value>),
83 Attribute {
85 attrs: HashMap<String, Resp3Value>,
87 data: Box<Resp3Value>,
89 },
90 Push(Vec<Resp3Value>),
92}
93
94impl std::hash::Hash for Resp3Value {
95 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
96 match self {
97 Self::SimpleString(s) => {
98 0u8.hash(state);
99 s.hash(state);
100 }
101 Self::SimpleError(s) => {
102 1u8.hash(state);
103 s.hash(state);
104 }
105 Self::Number(n) => {
106 2u8.hash(state);
107 n.hash(state);
108 }
109 Self::BlobString(s) => {
110 3u8.hash(state);
111 s.hash(state);
112 }
113 Self::Array(arr) => {
114 4u8.hash(state);
115 arr.hash(state);
116 }
117 Self::Null => {
118 5u8.hash(state);
119 }
120 Self::Boolean(b) => {
121 6u8.hash(state);
122 b.hash(state);
123 }
124 Self::Double(f) => {
125 7u8.hash(state);
126 f.to_bits().hash(state);
127 }
128 Self::BigNumber(s) => {
129 8u8.hash(state);
130 s.hash(state);
131 }
132 Self::BlobError(s) => {
133 9u8.hash(state);
134 s.hash(state);
135 }
136 Self::VerbatimString { encoding, data } => {
137 10u8.hash(state);
138 encoding.hash(state);
139 data.hash(state);
140 }
141 Self::Map(map) => {
142 11u8.hash(state);
143 let mut pairs: Vec<_> = map.iter().collect();
145 pairs.sort_by_key(|(k, _)| *k);
146 pairs.hash(state);
147 }
148 Self::Set(set) => {
149 12u8.hash(state);
150 let mut items: Vec<_> = set.iter().collect();
152 items.sort_by(|a, b| format!("{:?}", a).cmp(&format!("{:?}", b)));
153 items.hash(state);
154 }
155 Self::Attribute { attrs, data } => {
156 13u8.hash(state);
157 let mut pairs: Vec<_> = attrs.iter().collect();
158 pairs.sort_by_key(|(k, _)| *k);
159 pairs.hash(state);
160 data.hash(state);
161 }
162 Self::Push(arr) => {
163 14u8.hash(state);
164 arr.hash(state);
165 }
166 }
167 }
168}
169
170impl Eq for Resp3Value {}
171
172impl Resp3Value {
173 pub fn as_string(&self) -> RedisResult<String> {
179 match self {
180 Self::SimpleString(s) | Self::BlobString(s) => Ok(s.clone()),
181 Self::VerbatimString { data, .. } => Ok(data.clone()),
182 Self::Number(n) => Ok(n.to_string()),
183 Self::Double(f) => Ok(f.to_string()),
184 Self::Boolean(b) => Ok(b.to_string()),
185 Self::BigNumber(s) => Ok(s.clone()),
186 Self::Null => Err(RedisError::Type("Value is null".to_string())),
187 _ => Err(RedisError::Type(format!(
188 "Cannot convert {:?} to string",
189 self
190 ))),
191 }
192 }
193
194 pub fn as_int(&self) -> RedisResult<i64> {
200 match self {
201 Self::Number(n) => Ok(*n),
202 Self::SimpleString(s) | Self::BlobString(s) => s
203 .parse::<i64>()
204 .map_err(|e| RedisError::Type(format!("Cannot parse '{}' to i64: {}", s, e))),
205 Self::Double(f) => Ok(*f as i64),
206 Self::Boolean(true) => Ok(1),
207 Self::Boolean(false) => Ok(0),
208 _ => Err(RedisError::Type(format!(
209 "Cannot convert {:?} to integer",
210 self
211 ))),
212 }
213 }
214
215 pub fn as_float(&self) -> RedisResult<f64> {
221 match self {
222 Self::Double(f) => Ok(*f),
223 Self::Number(n) => Ok(*n as f64),
224 Self::SimpleString(s) | Self::BlobString(s) => s
225 .parse::<f64>()
226 .map_err(|e| RedisError::Type(format!("Cannot parse '{}' to f64: {}", s, e))),
227 _ => Err(RedisError::Type(format!(
228 "Cannot convert {:?} to float",
229 self
230 ))),
231 }
232 }
233
234 pub fn as_bool(&self) -> RedisResult<bool> {
240 match self {
241 Self::Boolean(b) => Ok(*b),
242 Self::Number(1) => Ok(true),
243 Self::Number(0) => Ok(false),
244 Self::SimpleString(s) if s == "OK" => Ok(true),
245 _ => Err(RedisError::Type(format!(
246 "Cannot convert {:?} to bool",
247 self
248 ))),
249 }
250 }
251
252 #[must_use]
254 pub const fn is_null(&self) -> bool {
255 matches!(self, Self::Null)
256 }
257
258 #[must_use]
260 pub const fn type_name(&self) -> &'static str {
261 match self {
262 Self::SimpleString(_) => "simple-string",
263 Self::SimpleError(_) => "simple-error",
264 Self::Number(_) => "number",
265 Self::BlobString(_) => "blob-string",
266 Self::Array(_) => "array",
267 Self::Null => "null",
268 Self::Boolean(_) => "boolean",
269 Self::Double(_) => "double",
270 Self::BigNumber(_) => "big-number",
271 Self::BlobError(_) => "blob-error",
272 Self::VerbatimString { .. } => "verbatim-string",
273 Self::Map(_) => "map",
274 Self::Set(_) => "set",
275 Self::Attribute { .. } => "attribute",
276 Self::Push(_) => "push",
277 }
278 }
279}
280
281impl From<Resp3Value> for RespValue {
283 fn from(value: Resp3Value) -> Self {
284 match value {
285 Resp3Value::SimpleString(s) => Self::SimpleString(s),
286 Resp3Value::SimpleError(s) => Self::Error(s),
287 Resp3Value::Number(n) => Self::Integer(n),
288 Resp3Value::BlobString(s) => Self::BulkString(Bytes::from(s.into_bytes())),
289 Resp3Value::Array(arr) => Self::Array(arr.into_iter().map(Into::into).collect()),
290 Resp3Value::Null => Self::Null,
291 Resp3Value::Boolean(true) => Self::Integer(1),
292 Resp3Value::Boolean(false) => Self::Integer(0),
293 Resp3Value::Double(f) => Self::BulkString(Bytes::from(f.to_string().into_bytes())),
294 Resp3Value::BigNumber(s) => Self::BulkString(Bytes::from(s.into_bytes())),
295 Resp3Value::BlobError(s) => Self::Error(s),
296 Resp3Value::VerbatimString { data, .. } => {
297 Self::BulkString(Bytes::from(data.into_bytes()))
298 }
299 Resp3Value::Map(map) => {
300 let mut arr = Vec::new();
301 for (k, v) in map {
302 arr.push(Self::BulkString(Bytes::from(k.into_bytes())));
303 arr.push(v.into());
304 }
305 Self::Array(arr)
306 }
307 Resp3Value::Set(set) => Self::Array(set.into_iter().map(Into::into).collect()),
308 Resp3Value::Attribute { data, .. } => (*data).into(),
309 Resp3Value::Push(arr) => Self::Array(arr.into_iter().map(Into::into).collect()),
310 }
311 }
312}
313
314impl From<RespValue> for Resp3Value {
316 fn from(value: RespValue) -> Self {
317 match value {
318 RespValue::SimpleString(s) => Self::SimpleString(s),
319 RespValue::Error(s) => Self::SimpleError(s),
320 RespValue::Integer(n) => Self::Number(n),
321 RespValue::BulkString(b) => Self::BlobString(String::from_utf8_lossy(&b).to_string()),
322 RespValue::Array(arr) => Self::Array(arr.into_iter().map(Into::into).collect()),
323 RespValue::Null => Self::Null,
324 }
325 }
326}
327
328pub struct Resp3Encoder {
330 buffer: BytesMut,
331}
332
333impl Resp3Encoder {
334 #[must_use]
336 pub fn new() -> Self {
337 Self {
338 buffer: BytesMut::new(),
339 }
340 }
341
342 pub fn encode(&mut self, value: &Resp3Value) -> RedisResult<Bytes> {
348 self.buffer.clear();
349 self.encode_value(value)?;
350 Ok(self.buffer.split().freeze())
351 }
352
353 fn encode_value(&mut self, value: &Resp3Value) -> RedisResult<()> {
354 match value {
355 Resp3Value::SimpleString(s) => {
356 self.buffer.put_u8(b'+');
357 self.buffer.extend_from_slice(s.as_bytes());
358 self.buffer.extend_from_slice(b"\r\n");
359 }
360 Resp3Value::SimpleError(s) => {
361 self.buffer.put_u8(b'-');
362 self.buffer.extend_from_slice(s.as_bytes());
363 self.buffer.extend_from_slice(b"\r\n");
364 }
365 Resp3Value::Number(n) => {
366 self.buffer.put_u8(b':');
367 self.buffer.extend_from_slice(n.to_string().as_bytes());
368 self.buffer.extend_from_slice(b"\r\n");
369 }
370 Resp3Value::BlobString(s) => {
371 self.buffer.put_u8(b'$');
372 self.buffer
373 .extend_from_slice(s.len().to_string().as_bytes());
374 self.buffer.extend_from_slice(b"\r\n");
375 self.buffer.extend_from_slice(s.as_bytes());
376 self.buffer.extend_from_slice(b"\r\n");
377 }
378 Resp3Value::Array(arr) => {
379 self.buffer.put_u8(b'*');
380 self.buffer
381 .extend_from_slice(arr.len().to_string().as_bytes());
382 self.buffer.extend_from_slice(b"\r\n");
383 for item in arr {
384 self.encode_value(item)?;
385 }
386 }
387 Resp3Value::Null => {
388 self.buffer.extend_from_slice(b"_\r\n");
389 }
390 Resp3Value::Boolean(b) => {
391 self.buffer.put_u8(b'#');
392 self.buffer.put_u8(if *b { b't' } else { b'f' });
393 self.buffer.extend_from_slice(b"\r\n");
394 }
395 Resp3Value::Double(f) => {
396 self.buffer.put_u8(b',');
397 self.buffer.extend_from_slice(f.to_string().as_bytes());
398 self.buffer.extend_from_slice(b"\r\n");
399 }
400 Resp3Value::BigNumber(s) => {
401 self.buffer.put_u8(b'(');
402 self.buffer.extend_from_slice(s.as_bytes());
403 self.buffer.extend_from_slice(b"\r\n");
404 }
405 Resp3Value::BlobError(s) => {
406 self.buffer.put_u8(b'!');
407 self.buffer
408 .extend_from_slice(s.len().to_string().as_bytes());
409 self.buffer.extend_from_slice(b"\r\n");
410 self.buffer.extend_from_slice(s.as_bytes());
411 self.buffer.extend_from_slice(b"\r\n");
412 }
413 Resp3Value::VerbatimString { encoding, data } => {
414 let content = format!("{}:{}", encoding, data);
415 self.buffer.put_u8(b'=');
416 self.buffer
417 .extend_from_slice(content.len().to_string().as_bytes());
418 self.buffer.extend_from_slice(b"\r\n");
419 self.buffer.extend_from_slice(content.as_bytes());
420 self.buffer.extend_from_slice(b"\r\n");
421 }
422 Resp3Value::Map(map) => {
423 self.buffer.put_u8(b'%');
424 self.buffer
425 .extend_from_slice(map.len().to_string().as_bytes());
426 self.buffer.extend_from_slice(b"\r\n");
427 for (k, v) in map {
428 self.encode_value(&Resp3Value::BlobString(k.clone()))?;
429 self.encode_value(v)?;
430 }
431 }
432 Resp3Value::Set(set) => {
433 self.buffer.put_u8(b'~');
434 self.buffer
435 .extend_from_slice(set.len().to_string().as_bytes());
436 self.buffer.extend_from_slice(b"\r\n");
437 for item in set {
438 self.encode_value(item)?;
439 }
440 }
441 Resp3Value::Attribute { attrs, data } => {
442 self.buffer.put_u8(b'|');
443 self.buffer
444 .extend_from_slice(attrs.len().to_string().as_bytes());
445 self.buffer.extend_from_slice(b"\r\n");
446 for (k, v) in attrs {
447 self.encode_value(&Resp3Value::BlobString(k.clone()))?;
448 self.encode_value(v)?;
449 }
450 self.encode_value(data)?;
451 }
452 Resp3Value::Push(arr) => {
453 self.buffer.put_u8(b'>');
454 self.buffer
455 .extend_from_slice(arr.len().to_string().as_bytes());
456 self.buffer.extend_from_slice(b"\r\n");
457 for item in arr {
458 self.encode_value(item)?;
459 }
460 }
461 }
462 Ok(())
463 }
464}
465
466impl Default for Resp3Encoder {
467 fn default() -> Self {
468 Self::new()
469 }
470}
471
472pub struct Resp3Decoder {
474 buffer: BytesMut,
475}
476
477impl Resp3Decoder {
478 #[must_use]
480 pub fn new() -> Self {
481 Self {
482 buffer: BytesMut::new(),
483 }
484 }
485
486 pub fn decode(&mut self, data: &[u8]) -> RedisResult<Resp3Value> {
492 self.buffer.extend_from_slice(data);
493 let mut cursor = Cursor::new(&self.buffer[..]);
494 let value = self.decode_value(&mut cursor)?;
495 let consumed = cursor.position() as usize;
496 self.buffer.advance(consumed);
497 Ok(value)
498 }
499
500 fn decode_value(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
501 if !cursor.has_remaining() {
502 return Err(RedisError::Protocol("Incomplete data".to_string()));
503 }
504
505 let type_byte = cursor.get_u8();
506 match type_byte {
507 b'+' => self.decode_simple_string(cursor),
508 b'-' => self.decode_simple_error(cursor),
509 b':' => self.decode_number(cursor),
510 b'$' => self.decode_blob_string(cursor),
511 b'*' => self.decode_array(cursor),
512 b'_' => self.decode_null(cursor),
513 b'#' => self.decode_boolean(cursor),
514 b',' => self.decode_double(cursor),
515 b'(' => self.decode_big_number(cursor),
516 b'!' => self.decode_blob_error(cursor),
517 b'=' => self.decode_verbatim_string(cursor),
518 b'%' => self.decode_map(cursor),
519 b'~' => self.decode_set(cursor),
520 b'|' => self.decode_attribute(cursor),
521 b'>' => self.decode_push(cursor),
522 _ => Err(RedisError::Protocol(format!(
523 "Unknown RESP3 type byte: {}",
524 type_byte as char
525 ))),
526 }
527 }
528
529 fn decode_simple_string(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
530 let line = self.read_line(cursor)?;
531 Ok(Resp3Value::SimpleString(line))
532 }
533
534 fn decode_simple_error(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
535 let line = self.read_line(cursor)?;
536 Ok(Resp3Value::SimpleError(line))
537 }
538
539 fn decode_number(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
540 let line = self.read_line(cursor)?;
541 let num = line
542 .parse::<i64>()
543 .map_err(|e| RedisError::Protocol(format!("Invalid number: {}", e)))?;
544 Ok(Resp3Value::Number(num))
545 }
546
547 fn decode_blob_string(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
548 let len_line = self.read_line(cursor)?;
549 let len = len_line
550 .parse::<i64>()
551 .map_err(|e| RedisError::Protocol(format!("Invalid blob string length: {}", e)))?;
552
553 if len == -1 {
554 return Ok(Resp3Value::Null);
555 }
556
557 if len < 0 {
558 return Err(RedisError::Protocol(
559 "Invalid blob string length".to_string(),
560 ));
561 }
562
563 let len = len as usize;
564 if cursor.remaining() < len + 2 {
565 return Err(RedisError::Protocol("Incomplete blob string".to_string()));
566 }
567
568 let mut data = vec![0u8; len];
569 cursor.copy_to_slice(&mut data);
570
571 if cursor.remaining() < 2 || cursor.get_u8() != b'\r' || cursor.get_u8() != b'\n' {
573 return Err(RedisError::Protocol(
574 "Invalid blob string terminator".to_string(),
575 ));
576 }
577
578 let string = String::from_utf8(data)
579 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8 in blob string: {}", e)))?;
580
581 Ok(Resp3Value::BlobString(string))
582 }
583
584 fn decode_array(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
585 let len_line = self.read_line(cursor)?;
586 let len = len_line
587 .parse::<i64>()
588 .map_err(|e| RedisError::Protocol(format!("Invalid array length: {}", e)))?;
589
590 if len == -1 {
591 return Ok(Resp3Value::Null);
592 }
593
594 if len < 0 {
595 return Err(RedisError::Protocol("Invalid array length".to_string()));
596 }
597
598 let len = len as usize;
599 let mut array = Vec::with_capacity(len);
600 for _ in 0..len {
601 array.push(self.decode_value(cursor)?);
602 }
603
604 Ok(Resp3Value::Array(array))
605 }
606
607 fn decode_null(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
608 let line = self.read_line(cursor)?;
609 if line.is_empty() {
610 Ok(Resp3Value::Null)
611 } else {
612 Err(RedisError::Protocol("Invalid null format".to_string()))
613 }
614 }
615
616 fn decode_boolean(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
617 let line = self.read_line(cursor)?;
618 match line.as_str() {
619 "t" => Ok(Resp3Value::Boolean(true)),
620 "f" => Ok(Resp3Value::Boolean(false)),
621 _ => Err(RedisError::Protocol(format!("Invalid boolean: {}", line))),
622 }
623 }
624
625 fn decode_double(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
626 let line = self.read_line(cursor)?;
627 let num = line
628 .parse::<f64>()
629 .map_err(|e| RedisError::Protocol(format!("Invalid double: {}", e)))?;
630 Ok(Resp3Value::Double(num))
631 }
632
633 fn decode_big_number(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
634 let line = self.read_line(cursor)?;
635 Ok(Resp3Value::BigNumber(line))
636 }
637
638 fn decode_blob_error(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
639 let len_line = self.read_line(cursor)?;
640 let len = len_line
641 .parse::<usize>()
642 .map_err(|e| RedisError::Protocol(format!("Invalid blob error length: {}", e)))?;
643
644 if cursor.remaining() < len + 2 {
645 return Err(RedisError::Protocol("Incomplete blob error".to_string()));
646 }
647
648 let mut data = vec![0u8; len];
649 cursor.copy_to_slice(&mut data);
650
651 if cursor.remaining() < 2 || cursor.get_u8() != b'\r' || cursor.get_u8() != b'\n' {
653 return Err(RedisError::Protocol(
654 "Invalid blob error terminator".to_string(),
655 ));
656 }
657
658 let string = String::from_utf8(data)
659 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8 in blob error: {}", e)))?;
660
661 Ok(Resp3Value::BlobError(string))
662 }
663
664 fn decode_verbatim_string(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
665 let len_line = self.read_line(cursor)?;
666 let len = len_line
667 .parse::<usize>()
668 .map_err(|e| RedisError::Protocol(format!("Invalid verbatim string length: {}", e)))?;
669
670 if cursor.remaining() < len + 2 {
671 return Err(RedisError::Protocol(
672 "Incomplete verbatim string".to_string(),
673 ));
674 }
675
676 let mut data = vec![0u8; len];
677 cursor.copy_to_slice(&mut data);
678
679 if cursor.remaining() < 2 || cursor.get_u8() != b'\r' || cursor.get_u8() != b'\n' {
681 return Err(RedisError::Protocol(
682 "Invalid verbatim string terminator".to_string(),
683 ));
684 }
685
686 let content = String::from_utf8(data).map_err(|e| {
687 RedisError::Protocol(format!("Invalid UTF-8 in verbatim string: {}", e))
688 })?;
689
690 if let Some(colon_pos) = content.find(':') {
692 let encoding = content[..colon_pos].to_string();
693 let data = content[colon_pos + 1..].to_string();
694 Ok(Resp3Value::VerbatimString { encoding, data })
695 } else {
696 Err(RedisError::Protocol(
697 "Invalid verbatim string format".to_string(),
698 ))
699 }
700 }
701
702 fn decode_map(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
703 let len_line = self.read_line(cursor)?;
704 let len = len_line
705 .parse::<usize>()
706 .map_err(|e| RedisError::Protocol(format!("Invalid map length: {}", e)))?;
707
708 let mut map = HashMap::new();
709 for _ in 0..len {
710 let key = self.decode_value(cursor)?;
711 let value = self.decode_value(cursor)?;
712 let key_str = key.as_string()?;
713 map.insert(key_str, value);
714 }
715
716 Ok(Resp3Value::Map(map))
717 }
718
719 fn decode_set(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
720 let len_line = self.read_line(cursor)?;
721 let len = len_line
722 .parse::<usize>()
723 .map_err(|e| RedisError::Protocol(format!("Invalid set length: {}", e)))?;
724
725 let mut set = HashSet::new();
726 for _ in 0..len {
727 let value = self.decode_value(cursor)?;
728 set.insert(value);
729 }
730
731 Ok(Resp3Value::Set(set))
732 }
733
734 fn decode_attribute(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
735 let len_line = self.read_line(cursor)?;
736 let len = len_line
737 .parse::<usize>()
738 .map_err(|e| RedisError::Protocol(format!("Invalid attribute length: {}", e)))?;
739
740 let mut attrs = HashMap::new();
741 for _ in 0..len {
742 let key = self.decode_value(cursor)?;
743 let value = self.decode_value(cursor)?;
744 let key_str = key.as_string()?;
745 attrs.insert(key_str, value);
746 }
747
748 let data = Box::new(self.decode_value(cursor)?);
749 Ok(Resp3Value::Attribute { attrs, data })
750 }
751
752 fn decode_push(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<Resp3Value> {
753 let len_line = self.read_line(cursor)?;
754 let len = len_line
755 .parse::<usize>()
756 .map_err(|e| RedisError::Protocol(format!("Invalid push length: {}", e)))?;
757
758 let mut array = Vec::with_capacity(len);
759 for _ in 0..len {
760 array.push(self.decode_value(cursor)?);
761 }
762
763 Ok(Resp3Value::Push(array))
764 }
765
766 fn read_line(&self, cursor: &mut Cursor<&[u8]>) -> RedisResult<String> {
767 let start = cursor.position() as usize;
768 let data = cursor.get_ref();
769
770 for i in start..data.len() - 1 {
771 if data[i] == b'\r' && data[i + 1] == b'\n' {
772 let line = String::from_utf8(data[start..i].to_vec())
773 .map_err(|e| RedisError::Protocol(format!("Invalid UTF-8 in line: {}", e)))?;
774 cursor.set_position((i + 2) as u64);
775 return Ok(line);
776 }
777 }
778
779 Err(RedisError::Protocol("Incomplete line".to_string()))
780 }
781}
782
783impl Default for Resp3Decoder {
784 fn default() -> Self {
785 Self::new()
786 }
787}
788
789#[cfg(test)]
790mod tests {
791 use super::*;
792
793 #[test]
794 fn test_encode_decode_simple_string() {
795 let mut encoder = Resp3Encoder::new();
796 let value = Resp3Value::SimpleString("OK".to_string());
797 let encoded = encoder.encode(&value).unwrap();
798
799 let mut decoder = Resp3Decoder::new();
800 let decoded = decoder.decode(&encoded).unwrap();
801
802 assert_eq!(value, decoded);
803 }
804
805 #[test]
806 fn test_encode_decode_number() {
807 let mut encoder = Resp3Encoder::new();
808 let value = Resp3Value::Number(42);
809 let encoded = encoder.encode(&value).unwrap();
810
811 let mut decoder = Resp3Decoder::new();
812 let decoded = decoder.decode(&encoded).unwrap();
813
814 assert_eq!(value, decoded);
815 }
816
817 #[test]
818 fn test_encode_decode_boolean() {
819 let mut encoder = Resp3Encoder::new();
820 let value = Resp3Value::Boolean(true);
821 let encoded = encoder.encode(&value).unwrap();
822
823 let mut decoder = Resp3Decoder::new();
824 let decoded = decoder.decode(&encoded).unwrap();
825
826 assert_eq!(value, decoded);
827 }
828
829 #[test]
830 fn test_encode_decode_double() {
831 let mut encoder = Resp3Encoder::new();
832 let value = Resp3Value::Double(3.14);
833 let encoded = encoder.encode(&value).unwrap();
834
835 let mut decoder = Resp3Decoder::new();
836 let decoded = decoder.decode(&encoded).unwrap();
837
838 assert_eq!(value, decoded);
839 }
840
841 #[test]
842 fn test_encode_decode_map() {
843 let mut encoder = Resp3Encoder::new();
844 let mut map = HashMap::new();
845 map.insert("key1".to_string(), Resp3Value::Number(1));
846 map.insert(
847 "key2".to_string(),
848 Resp3Value::SimpleString("value2".to_string()),
849 );
850 let value = Resp3Value::Map(map);
851 let encoded = encoder.encode(&value).unwrap();
852
853 let mut decoder = Resp3Decoder::new();
854 let decoded = decoder.decode(&encoded).unwrap();
855
856 assert_eq!(value, decoded);
857 }
858
859 #[test]
860 fn test_encode_decode_set() {
861 let mut encoder = Resp3Encoder::new();
862 let mut set = HashSet::new();
863 set.insert(Resp3Value::SimpleString("apple".to_string()));
864 set.insert(Resp3Value::SimpleString("banana".to_string()));
865 let value = Resp3Value::Set(set);
866 let encoded = encoder.encode(&value).unwrap();
867
868 let mut decoder = Resp3Decoder::new();
869 let decoded = decoder.decode(&encoded).unwrap();
870
871 assert_eq!(value, decoded);
872 }
873
874 #[test]
875 fn test_encode_decode_array() {
876 let mut encoder = Resp3Encoder::new();
877 let value = Resp3Value::Array(vec![
878 Resp3Value::SimpleString("hello".to_string()),
879 Resp3Value::Number(42),
880 Resp3Value::Boolean(true),
881 ]);
882 let encoded = encoder.encode(&value).unwrap();
883
884 let mut decoder = Resp3Decoder::new();
885 let decoded = decoder.decode(&encoded).unwrap();
886
887 assert_eq!(value, decoded);
888 }
889
890 #[test]
891 fn test_resp2_compatibility() {
892 let resp2_value = RespValue::SimpleString("test".to_string());
893 let resp3_value: Resp3Value = resp2_value.clone().into();
894 let back_to_resp2: RespValue = resp3_value.into();
895
896 assert_eq!(resp2_value, back_to_resp2);
897 }
898
899 #[test]
900 fn test_value_conversions() {
901 let value = Resp3Value::Number(42);
902 assert_eq!(value.as_int().unwrap(), 42);
903 assert_eq!(value.as_string().unwrap(), "42");
904
905 let value = Resp3Value::Boolean(true);
906 assert!(value.as_bool().unwrap());
907 assert_eq!(value.as_int().unwrap(), 1);
908
909 let value = Resp3Value::Double(std::f64::consts::PI);
910 assert!(
911 (value.as_float().unwrap() - std::f64::consts::PI).abs() < 1e-10,
912 "Float value differs from PI"
913 );
914 }
915}