implement serde for HashSet and tests

This commit is contained in:
Gwilym Inzani 2024-10-30 10:56:19 +00:00
parent 69219e3d73
commit b71c544b9a
2 changed files with 122 additions and 3 deletions

View file

@ -19,3 +19,4 @@ serde = { version = "1", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, features = ["small_rng"] } rand = { version = "0.8", default-features = false, features = ["small_rng"] }
lazy_static = "1.4" lazy_static = "1.4"
quickcheck = "1" quickcheck = "1"
serde_json = { version = "1", default-features = false, features = ["alloc"] }

View file

@ -1,11 +1,11 @@
use core::{hash::Hash, marker::PhantomData}; use core::{hash::Hash, marker::PhantomData};
use serde::{ use serde::{
de::{MapAccess, Visitor}, de::{MapAccess, SeqAccess, Visitor},
ser::SerializeMap, ser::SerializeMap,
Deserialize, Serialize, Deserialize, Serialize,
}; };
use crate::{ClonableAllocator, HashMap}; use crate::{ClonableAllocator, HashMap, HashSet};
mod hashmap { mod hashmap {
use super::*; use super::*;
@ -40,7 +40,6 @@ mod hashmap {
} }
} }
#[derive(Default)]
struct HashMapVisitor<K, V> { struct HashMapVisitor<K, V> {
_marker: PhantomData<fn() -> HashMap<K, V>>, _marker: PhantomData<fn() -> HashMap<K, V>>,
} }
@ -78,3 +77,122 @@ mod hashmap {
} }
} }
} }
mod hashset {
use super::*;
impl<K: Serialize, ALLOCATOR: ClonableAllocator> Serialize for HashSet<K, ALLOCATOR> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.collect_seq(self)
}
}
struct HashSetVisitor<K> {
_marker: PhantomData<fn() -> HashSet<K>>,
}
impl<K> HashSetVisitor<K> {
fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<'de, K> Visitor<'de> for HashSetVisitor<K>
where
K: Deserialize<'de> + Hash + Eq,
{
type Value = HashSet<K>;
fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
formatter.write_str("an agb::HashSet")
}
fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut set = HashSet::with_capacity(access.size_hint().unwrap_or(8));
while let Some(value) = access.next_element()? {
set.insert(value);
}
Ok(set)
}
}
impl<'de, K> Deserialize<'de> for HashSet<K>
where
K: Deserialize<'de> + Hash + Eq,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(HashSetVisitor::new())
}
}
}
#[cfg(test)]
mod test {
use alloc::{
string::{String, ToString},
vec::Vec,
};
use crate::{HashMap, HashSet};
#[test]
fn deserialize_map() {
let json = r#"
{
"three": 3,
"seven": 7
}
"#;
let map = serde_json::from_str::<HashMap<String, i32>>(json).unwrap();
assert_eq!(
map,
HashMap::from_iter([("three".to_string(), 3), ("seven".to_string(), 7)])
);
}
#[test]
fn serialize_map() {
let map = HashMap::from_iter([("three".to_string(), 3), ("seven".to_string(), 7)]);
let json = serde_json::to_string(&map).unwrap();
let possibilities = &[r#"{"three":3,"seven":7}"#, r#"{"seven":7,"three":3}"#];
assert!(possibilities.contains(&json.as_str()));
}
#[test]
fn deserialize_hashset() {
let json = "[1, 2, 5, 8, 9, 3, 4]";
let set = serde_json::from_str::<HashSet<i32>>(json).unwrap();
assert_eq!(set, HashSet::from_iter([1, 2, 3, 4, 5, 8, 9]));
}
#[test]
fn serialize_hashset() {
let set = HashSet::from_iter([1, 2, 3, 5, 8, 9, 10]);
let serialized = serde_json::to_string(&set).unwrap();
let mut deserialized = serde_json::from_str::<Vec<i32>>(&serialized).unwrap();
deserialized.sort();
assert_eq!(deserialized, &[1, 2, 3, 5, 8, 9, 10]);
}
}