From caa71b5d9fd070a41371cf28c64975c1915079fc Mon Sep 17 00:00:00 2001 From: Trangar Date: Thu, 3 Mar 2022 15:23:53 +0100 Subject: [PATCH] Added HashSet (#516) * Added HashSet * Added hashset to the same tests that hashmap has --- fuzz/fuzz_targets/roundtrip.rs | 3 ++- src/features/impl_std.rs | 36 +++++++++++++++++++++++++++++++++- src/lib.rs | 2 +- tests/alloc.rs | 1 + tests/std.rs | 5 +++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/fuzz/fuzz_targets/roundtrip.rs b/fuzz/fuzz_targets/roundtrip.rs index e2a15e8..10c19cd 100644 --- a/fuzz/fuzz_targets/roundtrip.rs +++ b/fuzz/fuzz_targets/roundtrip.rs @@ -1,7 +1,7 @@ #![no_main] use libfuzzer_sys::fuzz_target; -use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}; use std::ffi::CString; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::num::{NonZeroI128, NonZeroI32, NonZeroU128, NonZeroU32}; @@ -14,6 +14,7 @@ use std::time::{Duration, SystemTime}; enum AllTypes { BTreeMap(BTreeMap), HashMap(HashMap), + HashSet(HashSet), BTreeSet(BTreeSet), VecDeque(VecDeque), Vec(Vec), diff --git a/src/features/impl_std.rs b/src/features/impl_std.rs index 4955b35..ab8ed00 100644 --- a/src/features/impl_std.rs +++ b/src/features/impl_std.rs @@ -6,8 +6,9 @@ use crate::{ }; use core::time::Duration; use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, ffi::{CStr, CString}, + hash::Hash, io::Read, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, path::{Path, PathBuf}, @@ -392,3 +393,36 @@ where Ok(map) } } + +impl Decode for HashSet +where + T: Decode + Eq + Hash, +{ + fn decode(decoder: &mut D) -> Result { + let len = crate::de::decode_slice_len(decoder)?; + decoder.claim_container_read::(len)?; + + let mut map = HashSet::new(); + for _ in 0..len { + // See the documentation on `unclaim_bytes_read` as to why we're doing this here + decoder.unclaim_bytes_read(core::mem::size_of::()); + + let key = T::decode(decoder)?; + map.insert(key); + } + Ok(map) + } +} + +impl Encode for HashSet +where + T: Encode, +{ + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + crate::enc::encode_slice_len(encoder, self.len())?; + for item in self.iter() { + item.encode(encoder)?; + } + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index a6a2817..d9c5936 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,7 @@ //! //! |Name |Default?|Supported types for Encode/Decode|Enabled methods |Other| //! |------|--------|-----------------------------------------|-----------------------------------------------------------------|-----| -//! |std | Yes |`HashMap`|`decode_from_std_read` and `encode_into_std_write`| +//! |std | Yes |`HashMap` and `HashSet`|`decode_from_std_read` and `encode_into_std_write`| //! |alloc | Yes |All common containers in alloc, like `Vec`, `String`, `Box`|`encode_to_vec`| //! |atomic| Yes |All `Atomic*` integer types, e.g. `AtomicUsize`, and `AtomicBool`|| //! |derive| Yes |||Enables the `BorrowDecode`, `Decode` and `Encode` derive macros| diff --git a/tests/alloc.rs b/tests/alloc.rs index 484c56f..84bffe0 100644 --- a/tests/alloc.rs +++ b/tests/alloc.rs @@ -129,6 +129,7 @@ fn test_container_limits() { #[cfg(feature = "std")] { validate_fail::>(slice); + validate_fail::>(slice); } } } diff --git a/tests/std.rs b/tests/std.rs index 528fa1f..658a421 100644 --- a/tests/std.rs +++ b/tests/std.rs @@ -101,6 +101,11 @@ fn test_std_commons() { map.insert("you".to_owned(), "doing?".to_owned()); the_same(map); + let mut set = std::collections::HashSet::new(); + set.insert("Hello".to_string()); + set.insert("World".to_string()); + the_same(set); + // Borrowed values let config = bincode::config::standard(); let mut buffer = [0u8; 1024];