Skip to content

Commit

Permalink
Hashset corresponding serde_impl
Browse files Browse the repository at this point in the history
  • Loading branch information
deven96 committed Feb 4, 2025
1 parent 1e1eecf commit 0502c1f
Showing 1 changed file with 103 additions and 2 deletions.
105 changes: 103 additions & 2 deletions src/serde_impls.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use serde::de::{MapAccess, Visitor};
use serde::de::{MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

use std::fmt::{self, Formatter};
use std::hash::{BuildHasher, Hash};
use std::marker::PhantomData;

use crate::{Guard, HashMap, HashMapRef};
use crate::{Guard, HashMap, HashMapRef, HashSet, HashSetRef};

struct MapVisitor<K, V, S> {
_marker: PhantomData<HashMap<K, V, S>>,
Expand Down Expand Up @@ -94,9 +94,93 @@ where
}
}

struct SetVisitor<K, S> {
_marker: PhantomData<HashSet<K, S>>,
}

impl<K, S, G> Serialize for HashSetRef<'_, K, S, G>
where
K: Serialize + Hash + Eq,
G: Guard,
S: BuildHasher,
{
fn serialize<Sr>(&self, serializer: Sr) -> Result<Sr::Ok, Sr::Error>
where
Sr: Serializer,
{
serializer.collect_seq(self)
}
}

impl<K, S> Serialize for HashSet<K, S>
where
K: Serialize + Hash + Eq,
S: BuildHasher,
{
fn serialize<Sr>(&self, serializer: Sr) -> Result<Sr::Ok, Sr::Error>
where
Sr: Serializer,
{
self.pin().serialize(serializer)
}
}

impl<'de, K, S> Deserialize<'de> for HashSet<K, S>
where
K: Deserialize<'de> + Hash + Eq,
S: Default + BuildHasher,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(SetVisitor::new())
}
}

impl<K, S> SetVisitor<K, S> {
pub(crate) fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}

impl<'de, K, S> Visitor<'de> for SetVisitor<K, S>
where
K: Deserialize<'de> + Hash + Eq,
S: Default + BuildHasher,
{
type Value = HashSet<K, S>;

fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "a map")
}

fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: SeqAccess<'de>,
{
let values = match access.size_hint() {
Some(size) => HashSet::with_capacity_and_hasher(size, S::default()),
None => HashSet::default(),
};

{
let values = values.pin();
while let Some(key) = access.next_element()? {
values.insert(key);
}
}

Ok(values)
}
}

#[cfg(test)]
mod test {
use crate::HashMap;
use crate::HashSet;

#[test]
fn test_map() {
Expand All @@ -114,4 +198,21 @@ mod test {

assert_eq!(map, deserialized);
}

#[test]
fn test_set() {
let map: HashSet<u8> = HashSet::new();
let guard = map.guard();

map.insert(0, &guard);
map.insert(1, &guard);
map.insert(2, &guard);
map.insert(3, &guard);
map.insert(4, &guard);

let serialized = serde_json::to_string(&map).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();

assert_eq!(map, deserialized);
}
}

0 comments on commit 0502c1f

Please sign in to comment.