|
10 | 10 |
|
11 | 11 | //! An implementation of the RESP protocol
|
12 | 12 |
|
| 13 | +use std::collections::HashMap; |
| 14 | +use std::hash::Hash; |
13 | 15 | use std::io;
|
14 | 16 | use std::str;
|
15 | 17 |
|
@@ -187,6 +189,30 @@ impl<T: FromResp> FromResp for Vec<T> {
|
187 | 189 | }
|
188 | 190 | }
|
189 | 191 |
|
| 192 | +impl<K: FromResp + Hash + Eq, T: FromResp> FromResp for HashMap<K, T> { |
| 193 | + fn from_resp_int(resp: RespValue) -> Result<HashMap<K, T>, Error> { |
| 194 | + match resp { |
| 195 | + RespValue::Array(ary) => { |
| 196 | + let mut map = HashMap::new(); |
| 197 | + let mut items = ary.into_iter(); |
| 198 | + |
| 199 | + while let Some(k) = items.next() { |
| 200 | + let key = K::from_resp(k)?; |
| 201 | + let value = T::from_resp(items.next().ok_or(error::resp( |
| 202 | + "Cannot convert an odd number of elements into a hashmap", |
| 203 | + "".into(), |
| 204 | + ))?)?; |
| 205 | + |
| 206 | + map.insert(key, value); |
| 207 | + } |
| 208 | + |
| 209 | + Ok(map) |
| 210 | + } |
| 211 | + _ => Err(error::resp("Cannot be converted into a hashmap", resp)), |
| 212 | + } |
| 213 | + } |
| 214 | +} |
| 215 | + |
190 | 216 | impl FromResp for () {
|
191 | 217 | fn from_resp_int(resp: RespValue) -> Result<(), Error> {
|
192 | 218 | match resp {
|
@@ -613,11 +639,13 @@ impl Decoder for RespCodec {
|
613 | 639 |
|
614 | 640 | #[cfg(test)]
|
615 | 641 | mod tests {
|
| 642 | + use std::collections::HashMap; |
| 643 | + |
616 | 644 | use bytes::BytesMut;
|
617 | 645 |
|
618 | 646 | use tokio_io::codec::{Decoder, Encoder};
|
619 | 647 |
|
620 |
| - use super::{FromResp, RespCodec, RespValue}; |
| 648 | + use super::{Error, FromResp, RespCodec, RespValue}; |
621 | 649 |
|
622 | 650 | #[test]
|
623 | 651 | fn test_bulk_string() {
|
@@ -675,4 +703,39 @@ mod tests {
|
675 | 703 | let resp_object = RespValue::Integer(50);
|
676 | 704 | assert_eq!(u32::from_resp(resp_object).unwrap(), 50);
|
677 | 705 | }
|
| 706 | + |
| 707 | + #[test] |
| 708 | + fn test_hashmap_conversion() { |
| 709 | + let mut expected = HashMap::new(); |
| 710 | + expected.insert("KEY1".to_string(), "VALUE1".to_string()); |
| 711 | + expected.insert("KEY2".to_string(), "VALUE2".to_string()); |
| 712 | + |
| 713 | + let resp_object = RespValue::Array(vec![ |
| 714 | + "KEY1".into(), |
| 715 | + "VALUE1".into(), |
| 716 | + "KEY2".into(), |
| 717 | + "VALUE2".into(), |
| 718 | + ]); |
| 719 | + assert_eq!( |
| 720 | + HashMap::<String, String>::from_resp(resp_object).unwrap(), |
| 721 | + expected |
| 722 | + ); |
| 723 | + } |
| 724 | + |
| 725 | + #[test] |
| 726 | + fn test_hashmap_conversion_fails_with_odd_length_array() { |
| 727 | + let resp_object = RespValue::Array(vec![ |
| 728 | + "KEY1".into(), |
| 729 | + "VALUE1".into(), |
| 730 | + "KEY2".into(), |
| 731 | + "VALUE2".into(), |
| 732 | + "KEY3".into(), |
| 733 | + ]); |
| 734 | + let res = HashMap::<String, String>::from_resp(resp_object); |
| 735 | + |
| 736 | + match res { |
| 737 | + Err(Error::RESP(_, _)) => {} |
| 738 | + _ => panic!("Should not be able to convert an odd number of elements to a hashmap"), |
| 739 | + } |
| 740 | + } |
678 | 741 | }
|
0 commit comments