1use std::{cmp, collections::HashMap, convert::TryFrom, hash::BuildHasher, hash::Hash, str};
3
4use ntex::codec::{Decoder, Encoder};
5use ntex::util::{Buf, BufMut, ByteString, Bytes, BytesMut};
6
7use super::errors::Error;
8
9pub struct Codec;
11
12impl Encoder for Codec {
13 type Item = Request;
14 type Error = Error;
15
16 fn encode(&self, msg: Request, buf: &mut BytesMut) -> Result<(), Self::Error> {
17 match msg {
18 Request::Array(ary) => {
19 write_header(b'*', ary.len() as i64, buf, 0);
20 for v in ary {
21 self.encode(v, buf)?;
22 }
23 }
24 Request::BulkString(bstr) => {
25 let len = bstr.0.len();
26 write_header(b'$', len as i64, buf, len + 2);
27 buf.extend_from_slice(&bstr.0[..]);
28 write_rn(buf);
29 }
30 Request::BulkStatic(bstr) => {
31 let len = bstr.len();
32 write_header(b'$', len as i64, buf, len + 2);
33 buf.extend_from_slice(bstr);
34 write_rn(buf);
35 }
36 Request::BulkInteger(i) => {
37 let mut buffer = itoa::Buffer::new();
38 let rendered = buffer.format(i);
39 write_header(b'$', rendered.len() as i64, buf, rendered.len() + 2);
40 buf.extend_from_slice(rendered.as_bytes());
41 write_rn(buf);
42 }
43 Request::String(ref string) => {
44 write_string(b'+', string, buf);
45 }
46 Request::Integer(val) => {
47 write_header(b':', val, buf, 0);
49 }
50 }
51 Ok(())
52 }
53}
54
55impl Decoder for Codec {
56 type Item = Response;
57 type Error = Error;
58
59 fn decode(&self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
60 match decode(buf, 0)? {
61 Some((pos, item)) => {
62 buf.advance(pos);
63 Ok(Some(item))
64 }
65 None => Ok(None),
66 }
67 }
68}
69
70#[derive(Debug, Clone, Eq, PartialEq, Hash)]
71pub struct BulkString(Bytes);
76
77impl BulkString {
78 pub fn from_static(data: &'static str) -> Self {
80 BulkString(Bytes::from_static(data.as_ref()))
81 }
82
83 pub fn from_bstatic(data: &'static [u8]) -> Self {
85 BulkString(Bytes::from_static(data))
86 }
87}
88
89impl From<ByteString> for BulkString {
90 fn from(val: ByteString) -> BulkString {
91 BulkString(val.into_bytes())
92 }
93}
94
95impl From<String> for BulkString {
96 fn from(val: String) -> BulkString {
97 BulkString(Bytes::from(val))
98 }
99}
100
101impl<'a> From<&'a String> for BulkString {
102 fn from(val: &'a String) -> BulkString {
103 BulkString(Bytes::copy_from_slice(val.as_ref()))
104 }
105}
106
107impl<'a> From<&'a str> for BulkString {
108 fn from(val: &'a str) -> BulkString {
109 BulkString(Bytes::copy_from_slice(val.as_bytes()))
110 }
111}
112
113impl<'a> From<&&'a str> for BulkString {
114 fn from(val: &&'a str) -> BulkString {
115 BulkString(Bytes::copy_from_slice(val.as_bytes()))
116 }
117}
118
119impl From<Bytes> for BulkString {
120 fn from(val: Bytes) -> BulkString {
121 BulkString(val)
122 }
123}
124
125impl From<BytesMut> for BulkString {
126 fn from(val: BytesMut) -> BulkString {
127 BulkString(val.freeze())
128 }
129}
130
131impl<'a> From<&'a Bytes> for BulkString {
132 fn from(val: &'a Bytes) -> BulkString {
133 BulkString(val.clone())
134 }
135}
136
137impl<'a> From<&'a ByteString> for BulkString {
138 fn from(val: &'a ByteString) -> BulkString {
139 BulkString(val.clone().into_bytes())
140 }
141}
142
143impl<'a> From<&'a [u8]> for BulkString {
144 fn from(val: &'a [u8]) -> BulkString {
145 BulkString(Bytes::copy_from_slice(val))
146 }
147}
148
149impl From<Vec<u8>> for BulkString {
150 fn from(val: Vec<u8>) -> BulkString {
151 BulkString(Bytes::from(val))
152 }
153}
154
155#[derive(Debug, Clone, Eq, PartialEq, Hash)]
160pub enum Request {
161 Array(Vec<Request>),
163
164 BulkString(BulkString),
167
168 BulkStatic(&'static [u8]),
171
172 BulkInteger(i64),
174
175 String(ByteString),
177
178 Integer(i64),
181}
182
183impl Request {
184 pub fn from_static(data: &'static str) -> Self {
186 Request::BulkStatic(data.as_ref())
187 }
188
189 pub fn from_bstatic(data: &'static [u8]) -> Self {
191 Request::BulkStatic(data)
192 }
193
194 #[allow(clippy::should_implement_trait)]
195 pub fn add<T>(mut self, other: T) -> Self
200 where
201 Request: From<T>,
202 {
203 match self {
204 Request::Array(ref mut vals) => {
205 vals.push(other.into());
206 self
207 }
208 _ => Request::Array(vec![self, other.into()]),
209 }
210 }
211
212 pub fn extend<T>(mut self, other: impl IntoIterator<Item = T>) -> Self
217 where
218 Request: From<T>,
219 {
220 match self {
221 Request::Array(ref mut vals) => {
222 vals.extend(other.into_iter().map(|t| t.into()));
223 self
224 }
225 _ => {
226 let mut vals = vec![self];
227 vals.extend(other.into_iter().map(|t| t.into()));
228 Request::Array(vals)
229 }
230 }
231 }
232}
233
234impl<T> From<T> for Request
235where
236 BulkString: From<T>,
237{
238 fn from(val: T) -> Request {
239 Request::BulkString(val.into())
240 }
241}
242
243impl From<i8> for Request {
244 fn from(val: i8) -> Request {
245 Request::Integer(val as i64)
246 }
247}
248
249impl From<i16> for Request {
250 fn from(val: i16) -> Request {
251 Request::Integer(val as i64)
252 }
253}
254
255impl From<i32> for Request {
256 fn from(val: i32) -> Request {
257 Request::Integer(val as i64)
258 }
259}
260
261impl From<i64> for Request {
262 fn from(val: i64) -> Request {
263 Request::Integer(val)
264 }
265}
266
267impl From<u8> for Request {
268 fn from(val: u8) -> Request {
269 Request::Integer(val as i64)
270 }
271}
272
273impl From<u16> for Request {
274 fn from(val: u16) -> Request {
275 Request::Integer(val as i64)
276 }
277}
278
279impl From<u32> for Request {
280 fn from(val: u32) -> Request {
281 Request::Integer(val as i64)
282 }
283}
284
285impl From<usize> for Request {
286 fn from(val: usize) -> Request {
287 Request::Integer(val as i64)
288 }
289}
290
291#[derive(Debug, Clone, Eq, PartialEq, Hash)]
293pub enum Response {
294 Nil,
295
296 Array(Vec<Response>),
298
299 Bytes(Bytes),
302
303 String(ByteString),
305
306 Error(ByteString),
308
309 Integer(i64),
312}
313
314impl Response {
315 pub fn into_result(self) -> Result<Response, ByteString> {
317 match self {
318 Response::Error(val) => Err(val),
319 val => Ok(val),
320 }
321 }
322}
323
324impl TryFrom<Response> for Bytes {
325 type Error = (&'static str, Response);
326
327 fn try_from(val: Response) -> Result<Self, Self::Error> {
328 if let Response::Bytes(bytes) = val {
329 Ok(bytes)
330 } else {
331 Err(("Not a bytes object", val))
332 }
333 }
334}
335
336impl TryFrom<Response> for ByteString {
337 type Error = (&'static str, Response);
338
339 fn try_from(val: Response) -> Result<Self, Self::Error> {
340 match val {
341 Response::String(val) => Ok(val),
342 Response::Bytes(val) => {
343 if let Ok(val) = ByteString::try_from(val) {
344 Ok(val)
345 } else {
346 Err(("Cannot convert into a string", Response::Nil))
347 }
348 }
349 _ => Err(("Cannot convert into a string", val)),
350 }
351 }
352}
353
354impl TryFrom<Response> for i64 {
355 type Error = (&'static str, Response);
356
357 fn try_from(val: Response) -> Result<Self, Self::Error> {
358 if let Response::Integer(i) = val {
359 Ok(i)
360 } else {
361 Err(("Cannot be converted into an i64", val))
362 }
363 }
364}
365
366impl TryFrom<Response> for bool {
367 type Error = (&'static str, Response);
368
369 fn try_from(val: Response) -> Result<bool, Self::Error> {
370 i64::try_from(val).and_then(|x| match x {
371 0 => Ok(false),
372 1 => Ok(true),
373 _ => Err((
374 "i64 value cannot be represented as bool",
375 Response::Integer(x),
376 )),
377 })
378 }
379}
380
381impl<T> TryFrom<Response> for Vec<T>
382where
383 T: TryFrom<Response, Error = (&'static str, Response)>,
384{
385 type Error = (&'static str, Response);
386
387 fn try_from(val: Response) -> Result<Vec<T>, Self::Error> {
388 if let Response::Array(ary) = val {
389 let mut ar = Vec::with_capacity(ary.len());
390 for value in ary {
391 ar.push(T::try_from(value)?);
392 }
393 Ok(ar)
394 } else {
395 Err(("Cannot be converted into a vector", val))
396 }
397 }
398}
399
400impl TryFrom<Response> for () {
401 type Error = (&'static str, Response);
402
403 fn try_from(val: Response) -> Result<(), Self::Error> {
404 if let Response::String(string) = val {
405 match string.as_ref() {
406 "OK" => Ok(()),
407 _ => Err(("Unexpected value within String", Response::String(string))),
408 }
409 } else {
410 Err(("Unexpected value", val))
411 }
412 }
413}
414
415impl<A, B> TryFrom<Response> for (A, B)
416where
417 A: TryFrom<Response, Error = (&'static str, Response)>,
418 B: TryFrom<Response, Error = (&'static str, Response)>,
419{
420 type Error = (&'static str, Response);
421
422 fn try_from(val: Response) -> Result<(A, B), Self::Error> {
423 match val {
424 Response::Array(ary) => {
425 if ary.len() == 2 {
426 let mut ary_iter = ary.into_iter();
427 Ok((
428 A::try_from(ary_iter.next().expect("No value"))?,
429 B::try_from(ary_iter.next().expect("No value"))?,
430 ))
431 } else {
432 Err(("Array needs to be 2 elements", Response::Array(ary)))
433 }
434 }
435 _ => Err(("Unexpected value", val)),
436 }
437 }
438}
439
440impl<A, B, C> TryFrom<Response> for (A, B, C)
441where
442 A: TryFrom<Response, Error = (&'static str, Response)>,
443 B: TryFrom<Response, Error = (&'static str, Response)>,
444 C: TryFrom<Response, Error = (&'static str, Response)>,
445{
446 type Error = (&'static str, Response);
447
448 fn try_from(val: Response) -> Result<(A, B, C), Self::Error> {
449 match val {
450 Response::Array(ary) => {
451 if ary.len() == 3 {
452 let mut ary_iter = ary.into_iter();
453 Ok((
454 A::try_from(ary_iter.next().expect("No value"))?,
455 B::try_from(ary_iter.next().expect("No value"))?,
456 C::try_from(ary_iter.next().expect("No value"))?,
457 ))
458 } else {
459 Err(("Array needs to be 3 elements", Response::Array(ary)))
460 }
461 }
462 _ => Err(("Unexpected value", val)),
463 }
464 }
465}
466
467impl<K, T, S> TryFrom<Response> for HashMap<K, T, S>
468where
469 K: TryFrom<Response, Error = (&'static str, Response)> + Hash + Eq,
470 T: TryFrom<Response, Error = (&'static str, Response)>,
471 S: BuildHasher + Default,
472{
473 type Error = (&'static str, Response);
474
475 fn try_from(val: Response) -> Result<HashMap<K, T, S>, Self::Error> {
476 match val {
477 Response::Array(ary) => {
478 let mut map = HashMap::with_capacity_and_hasher(ary.len() / 2, S::default());
479 let mut items = ary.into_iter();
480
481 while let Some(k) = items.next() {
482 let key = K::try_from(k)?;
483 let value = T::try_from(items.next().ok_or((
484 "Cannot convert an odd number of elements into a hashmap",
485 Response::Nil,
486 ))?)?;
487 map.insert(key, value);
488 }
489
490 Ok(map)
491 }
492 _ => Err(("Cannot be converted into a hashmap", val)),
493 }
494 }
495}
496
497macro_rules! impl_tryfrom_integers {
498 ($($int_ty:ident),* $(,)*) => {
499 $(
500 #[allow(clippy::cast_lossless)]
501 impl TryFrom<Response> for $int_ty {
502 type Error = (&'static str, Response);
503
504 fn try_from(val: Response) -> Result<Self, Self::Error> {
505 i64::try_from(val).and_then(|x| {
506 if x < ($int_ty::min_value() as i64)
509 || ($int_ty::max_value() as i64 > 0
510 && x > ($int_ty::max_value() as i64))
511 {
512 Err((
513 concat!(
514 "i64 value cannot be represented as {}",
515 stringify!($int_ty),
516 ),
517 Response::Integer(x),
518 ))
519 } else {
520 Ok(x as $int_ty)
521 }
522 })
523 }
524 }
525 )*
526 };
527}
528
529impl_tryfrom_integers!(isize, usize, i32, u32, u64);
530
531fn write_rn(buf: &mut BytesMut) {
532 buf.extend_from_slice(b"\r\n");
533}
534
535fn write_header(symb: u8, len: i64, buf: &mut BytesMut, body_size: usize) {
536 let mut len_buf = itoa::Buffer::new();
537 let rendered = len_buf.format(len);
538 buf.reserve(3 + rendered.len() + body_size);
539 buf.put_u8(symb);
540 buf.extend_from_slice(rendered.as_bytes());
541 write_rn(buf);
542}
543
544fn write_string(symb: u8, string: &str, buf: &mut BytesMut) {
545 let bytes = string.as_bytes();
546 buf.reserve(3 + bytes.len());
547 buf.put_u8(symb);
548 buf.extend_from_slice(bytes);
549 write_rn(buf);
550}
551
552type DecodeResult = Result<Option<(usize, Response)>, Error>;
553
554fn decode(buf: &mut BytesMut, idx: usize) -> DecodeResult {
555 if buf.len() > idx {
556 match buf[idx] {
557 b'$' => decode_bytes(buf, idx + 1),
558 b'*' => decode_array(buf, idx + 1),
559 b':' => decode_integer(buf, idx + 1),
560 b'+' => decode_string(buf, idx + 1),
561 b'-' => decode_error(buf, idx + 1),
562 _ => Err(Error::Parse(format!("Unexpected byte: {}", buf[idx]))),
563 }
564 } else {
565 Ok(None)
566 }
567}
568
569fn decode_length(buf: &mut BytesMut, idx: usize) -> Result<Option<(usize, i64)>, Error> {
570 let (pos, int_str) = if let Some(pos) = buf[idx..].windows(2).position(|w| w == b"\r\n") {
572 (idx + pos + 2, &buf[idx..idx + pos])
573 } else {
574 return Ok(None);
575 };
576
577 match btoi::btoi(int_str) {
579 Ok(int) => Ok(Some((pos, int))),
580 Err(_) => Err(Error::Parse(format!(
581 "Not an integer: {:?}",
582 &int_str[..cmp::min(int_str.len(), 10)]
583 ))),
584 }
585}
586
587fn decode_bytes(buf: &mut BytesMut, idx: usize) -> DecodeResult {
588 match decode_length(buf, idx)? {
589 Some((pos, -1)) => Ok(Some((pos, Response::Nil))),
590 Some((pos, size)) if size >= 0 => {
591 let size = size as usize;
592 let remaining = buf.len() - pos;
593 let required_bytes = size + 2;
594
595 if remaining < required_bytes {
596 return Ok(None);
597 }
598 buf.advance(pos);
599 Ok(Some((2, Response::Bytes(buf.split_to(size).freeze()))))
600 }
601 Some((_, size)) => Err(Error::Parse(format!("Invalid string size: {}", size))),
602 None => Ok(None),
603 }
604}
605
606fn is_array_ready_to_decode(
607 buf: &mut BytesMut,
608 idx: usize,
609 array_size: usize,
610) -> Result<(bool, usize), Error> {
611 let mut items: usize = 0;
612 let mut pos = idx;
613
614 loop {
616 let Some(new_pos) = buf[pos..].windows(2).position(|w| w.starts_with(b"\r\n")) else {
617 break;
618 };
619
620 if pos + new_pos + 2 >= buf.len() {
621 break;
622 }
623 pos += new_pos + 2;
624
625 items += match &buf[pos] {
626 b'*' => match decode_length(buf, pos) {
628 Ok(Some((_, -1))) => 1,
629 Ok(Some((p, size))) if size >= 0 => {
630 let (ready, end_of_scan) = is_array_ready_to_decode(buf, p, size as usize)?;
631 if !ready {
633 return Ok((false, end_of_scan));
634 }
635 pos = end_of_scan;
636 1
637 }
638 Ok(Some((_, size))) => {
639 return Err(Error::Parse(format!("Invalid array size: {}", size)))
640 }
641 _ => 0,
642 },
643 b'$' | b':' | b'+' | b'-' => 1,
645 _ => 0,
646 };
647
648 if array_size <= items {
649 return Ok((true, pos));
650 }
651 }
652
653 Ok((array_size <= items, pos))
654}
655
656fn decode_array(buf: &mut BytesMut, idx: usize) -> DecodeResult {
657 match decode_length(buf, idx)? {
658 Some((pos, -1)) => Ok(Some((pos, Response::Nil))),
659 Some((pos, size)) if size >= 0 => {
660 let size = size as usize;
661
662 let (is_ready, _) = is_array_ready_to_decode(buf, idx, size)?;
663 if !is_ready {
664 return Ok(None);
665 }
666
667 let mut pos = pos;
668 let mut values = Vec::with_capacity(size);
669 for _ in 0..size {
670 match decode(buf, pos) {
671 Ok(None) => return Ok(None),
672 Ok(Some((new_pos, value))) => {
673 values.push(value);
674 pos = new_pos;
675 }
676 Err(e) => return Err(e),
677 }
678 }
679 Ok(Some((pos, Response::Array(values))))
680 }
681 Some((_, size)) => Err(Error::Parse(format!("Invalid array size: {}", size))),
682 None => Ok(None),
683 }
684}
685
686fn decode_integer(buf: &mut BytesMut, idx: usize) -> DecodeResult {
687 if let Some((pos, int)) = decode_length(buf, idx)? {
688 Ok(Some((pos, Response::Integer(int))))
689 } else {
690 Ok(None)
691 }
692}
693
694fn decode_string(buf: &mut BytesMut, idx: usize) -> DecodeResult {
696 if let Some((pos, string)) = scan_string(buf, idx)? {
697 Ok(Some((pos, Response::String(string))))
698 } else {
699 Ok(None)
700 }
701}
702
703fn decode_error(buf: &mut BytesMut, idx: usize) -> DecodeResult {
704 if let Some((pos, string)) = scan_string(buf, idx)? {
705 Ok(Some((pos, Response::Error(string))))
706 } else {
707 Ok(None)
708 }
709}
710
711fn scan_string(buf: &mut BytesMut, idx: usize) -> Result<Option<(usize, ByteString)>, Error> {
712 if let Some(pos) = buf[idx..].windows(2).position(|w| w == b"\r\n") {
713 buf.advance(idx);
714 match ByteString::try_from(buf.split_to(pos)) {
715 Ok(s) => Ok(Some((2, s))),
716 Err(_) => Err(Error::Parse(format!(
717 "Not a valid string: {:?}",
718 &buf[idx..idx + cmp::min(pos, 10)]
719 ))),
720 }
721 } else {
722 Ok(None)
723 }
724}
725
726#[cfg(test)]
727mod tests {
728 use std::convert::TryFrom;
729
730 use ntex::codec::{Decoder, Encoder};
731 use ntex::util::{ByteString, Bytes, BytesMut, HashMap};
732
733 use super::*;
734 use crate::array;
735
736 fn obj_to_bytes(obj: Request) -> Bytes {
737 let mut bytes = BytesMut::new();
738 Codec.encode(obj, &mut bytes).unwrap();
739 bytes.freeze()
740 }
741
742 #[test]
743 fn test_array_macro() {
744 let resp_object = array!["SET", "x"];
745 let bytes = obj_to_bytes(resp_object);
746 assert_eq!(bytes, b"*2\r\n$3\r\nSET\r\n$1\r\nx\r\n".as_ref());
747
748 let resp_object = array!["RPUSH", "wyz"].extend(vec!["a", "b"]);
749 let bytes = obj_to_bytes(resp_object);
750 assert_eq!(
751 bytes,
752 b"*4\r\n$5\r\nRPUSH\r\n$3\r\nwyz\r\n$1\r\na\r\n$1\r\nb\r\n".as_ref(),
753 );
754
755 let vals = vec!["a", "b"];
756 let resp_object = array!["RPUSH", "xyz"].extend(&vals);
757 let bytes = obj_to_bytes(resp_object);
758 assert_eq!(
759 bytes,
760 &b"*4\r\n$5\r\nRPUSH\r\n$3\r\nxyz\r\n$1\r\na\r\n$1\r\nb\r\n"[..],
761 );
762 }
763
764 #[test]
765 fn test_bulk_string() {
766 let req_object = Request::BulkString(Bytes::from_static(b"THISISATEST").into());
767 let mut bytes = BytesMut::new();
768 let codec = Codec;
769 codec.encode(req_object.clone(), &mut bytes).unwrap();
770 assert_eq!(b"$11\r\nTHISISATEST\r\n".to_vec(), bytes.to_vec());
771
772 let resp_object = Response::Bytes(Bytes::from_static(b"THISISATEST"));
773 let deserialized = codec.decode(&mut bytes).unwrap().unwrap();
774 assert_eq!(deserialized, resp_object);
775 }
776
777 #[test]
778 fn test_array() {
779 let req_object = Request::Array(vec![b"TEST1".as_ref().into(), b"TEST2".as_ref().into()]);
780 let mut bytes = BytesMut::new();
781 let codec = Codec;
782 codec.encode(req_object.clone(), &mut bytes).unwrap();
783 assert_eq!(
784 b"*2\r\n$5\r\nTEST1\r\n$5\r\nTEST2\r\n".to_vec(),
785 bytes.to_vec()
786 );
787
788 let resp = Response::Array(vec![
789 Response::Bytes(Bytes::from_static(b"TEST1")),
790 Response::Bytes(Bytes::from_static(b"TEST2")),
791 ]);
792 let deserialized = codec.decode(&mut bytes).unwrap().unwrap();
793 assert_eq!(deserialized, resp);
794 }
795
796 #[test]
797 fn test_decode_array() {
798 let codec = Codec;
799
800 let resp = Response::Array(vec![
801 Response::Bytes(Bytes::from_static(b"TEST1")),
802 Response::Bytes(Bytes::from_static(b"TEST2")),
803 ]);
804
805 let mut bytes = BytesMut::copy_from_slice(b"*2\r\n$5\r\nTEST1\r\n$5\r\nTEST2\r\n");
806 let deserialized = codec.decode(&mut bytes).unwrap().unwrap();
807 assert_eq!(deserialized, resp);
808
809 let mut bytes = BytesMut::copy_from_slice(b"*2\r\n$5\r\nTEST1\r\n");
811 let result = codec.decode(&mut bytes).unwrap();
812 assert!(result.is_none());
813
814 bytes.extend_from_slice(b"$5\r\nTEST2\r\n");
816
817 let deserialized = codec.decode(&mut bytes).unwrap().unwrap();
818 assert_eq!(deserialized, resp);
819
820 let mut bytes = BytesMut::copy_from_slice(b"*2\r\n$-1\r\n$-1\r\n");
823 let result = codec.decode(&mut bytes).unwrap();
824
825 assert_eq!(
826 result,
827 Some(Response::Array(vec![Response::Nil, Response::Nil]))
828 );
829
830 let mut bytes = BytesMut::copy_from_slice(b"*1\r\n*1\r\n*1\r\n");
835 let result = codec.decode(&mut bytes).unwrap();
836 assert_eq!(result, None);
837
838 bytes.extend_from_slice(b"$1\r\na");
840 let result = codec.decode(&mut bytes).unwrap();
841 assert_eq!(result, None);
842
843 bytes.extend_from_slice(b"\r");
844 let result = codec.decode(&mut bytes).unwrap();
845 assert_eq!(result, None);
846
847 bytes.extend_from_slice(b"\n");
848 let result = codec.decode(&mut bytes).unwrap();
849
850 assert_eq!(
851 result,
852 Some(Response::Array(vec![Response::Array(vec![
853 Response::Array(vec![Response::Bytes(Bytes::from_static(b"a"))])
854 ])]))
855 );
856 }
857
858 #[test]
859 fn test_nil_string() {
860 let mut bytes = BytesMut::new();
861 bytes.extend_from_slice(&b"$-1\r\n"[..]);
862
863 let codec = Codec;
864 let deserialized = codec.decode(&mut bytes).unwrap().unwrap();
865 assert_eq!(deserialized, Response::Nil);
866 }
867
868 #[test]
869 fn test_integer_overflow() {
870 let resp_object = Response::Integer(i64::max_value());
871 let res = i32::try_from(resp_object);
872 assert!(res.is_err());
873 }
874
875 #[test]
876 fn test_integer_underflow() {
877 let resp_object = Response::Integer(-2);
878 let res = u64::try_from(resp_object);
879 assert!(res.is_err());
880 }
881
882 #[test]
883 fn test_integer_convesion() {
884 let resp_object = Response::Integer(50);
885 assert_eq!(u32::try_from(resp_object).unwrap(), 50);
886 }
887
888 #[test]
889 fn test_hashmap_conversion() {
890 let mut expected = HashMap::default();
891 expected.insert(
892 ByteString::from("KEY1").into(),
893 ByteString::from("VALUE1").into(),
894 );
895 expected.insert(
896 ByteString::from("KEY2").into(),
897 ByteString::from("VALUE2").into(),
898 );
899
900 let resp_object = Response::Array(vec![
901 Response::String(ByteString::from_static("KEY1")),
902 Response::String(ByteString::from_static("VALUE1")),
903 Response::String(ByteString::from_static("KEY2")),
904 Response::String(ByteString::from_static("VALUE2")),
905 ]);
906 assert_eq!(
907 HashMap::<ByteString, ByteString>::try_from(resp_object).unwrap(),
908 expected
909 );
910 }
911
912 #[test]
913 fn test_hashmap_conversion_fails_with_odd_length_array() {
914 let resp_object = Response::Array(vec![
915 Response::String(ByteString::from_static("KEY1")),
916 Response::String(ByteString::from_static("VALUE1")),
917 Response::String(ByteString::from_static("KEY2")),
918 Response::String(ByteString::from_static("VALUE2")),
919 Response::String(ByteString::from_static("KEY3")),
920 ]);
921 let res = HashMap::<ByteString, ByteString>::try_from(resp_object);
922
923 match res {
924 Err((_, _)) => {}
925 _ => panic!("Should not be able to convert an odd number of elements to a hashmap"),
926 }
927 }
928}