rkyv/impls/std/collections/
hash_set.rs

1use core::{
2    borrow::Borrow,
3    hash::{BuildHasher, Hash},
4};
5use std::collections::HashSet;
6
7use rancor::{Fallible, Source};
8
9use crate::{
10    collections::swiss_table::set::{ArchivedHashSet, HashSetResolver},
11    ser::{Allocator, Writer},
12    Archive, Deserialize, Place, Serialize,
13};
14
15impl<K, S> Archive for HashSet<K, S>
16where
17    K: Archive + Hash + Eq,
18    K::Archived: Hash + Eq,
19{
20    type Archived = ArchivedHashSet<K::Archived>;
21    type Resolver = HashSetResolver;
22
23    fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
24        ArchivedHashSet::<K::Archived>::resolve_from_len(
25            self.len(),
26            (7, 8),
27            resolver,
28            out,
29        );
30    }
31}
32
33impl<K, S, RS> Serialize<S> for HashSet<K, RS>
34where
35    K::Archived: Hash + Eq,
36    K: Serialize<S> + Hash + Eq,
37    S: Fallible + Allocator + Writer + ?Sized,
38    S::Error: Source,
39{
40    fn serialize(
41        &self,
42        serializer: &mut S,
43    ) -> Result<Self::Resolver, S::Error> {
44        ArchivedHashSet::<K::Archived>::serialize_from_iter::<_, K, _>(
45            self.iter(),
46            (7, 8),
47            serializer,
48        )
49    }
50}
51
52impl<K, D, S> Deserialize<HashSet<K, S>, D> for ArchivedHashSet<K::Archived>
53where
54    K: Archive + Hash + Eq,
55    K::Archived: Deserialize<K, D> + Hash + Eq,
56    D: Fallible + ?Sized,
57    S: Default + BuildHasher,
58{
59    fn deserialize(
60        &self,
61        deserializer: &mut D,
62    ) -> Result<HashSet<K, S>, D::Error> {
63        let mut result = HashSet::with_hasher(S::default());
64        for k in self.iter() {
65            result.insert(k.deserialize(deserializer)?);
66        }
67        Ok(result)
68    }
69}
70
71impl<K: Hash + Eq + Borrow<AK>, AK: Hash + Eq, S: BuildHasher>
72    PartialEq<HashSet<K, S>> for ArchivedHashSet<AK>
73{
74    fn eq(&self, other: &HashSet<K, S>) -> bool {
75        if self.len() != other.len() {
76            false
77        } else {
78            self.iter().all(|key| other.get(key).is_some())
79        }
80    }
81}
82
83impl<K: Hash + Eq + Borrow<AK>, AK: Hash + Eq, S: BuildHasher>
84    PartialEq<ArchivedHashSet<AK>> for HashSet<K, S>
85{
86    fn eq(&self, other: &ArchivedHashSet<AK>) -> bool {
87        other.eq(self)
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use std::collections::HashSet;
94
95    use crate::api::test::{roundtrip, roundtrip_with};
96
97    #[test]
98    fn roundtrip_hash_set() {
99        let mut hash_set = HashSet::new();
100        hash_set.insert("hello".to_string());
101        hash_set.insert("world".to_string());
102        hash_set.insert("foo".to_string());
103        hash_set.insert("bar".to_string());
104        hash_set.insert("baz".to_string());
105
106        roundtrip_with(&hash_set, |a, b| {
107            assert_eq!(a.len(), b.len());
108
109            for key in a.iter() {
110                assert!(b.contains(key.as_str()));
111            }
112
113            for key in b.iter() {
114                assert!(a.contains(key.as_str()));
115            }
116        });
117    }
118
119    #[test]
120    fn roundtrip_hash_set_zst() {
121        let mut value = HashSet::new();
122        value.insert(());
123        roundtrip(&value);
124    }
125}