Skip to content

Commit

Permalink
Implement deserialize_in_place() in Deserialize for AHashMap and AHas…
Browse files Browse the repository at this point in the history
…hSet (#110)
  • Loading branch information
orzogc authored Feb 26, 2022
1 parent 5e55048 commit f2aecc0
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
44 changes: 42 additions & 2 deletions src/hash_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,40 @@ where
let hash_map = HashMap::deserialize(deserializer);
hash_map.map(|hash_map| Self(hash_map))
}

fn deserialize_in_place<D: Deserializer<'de>>(deserializer: D, place: &mut Self) -> Result<(), D::Error> {
use serde::de::{MapAccess, Visitor};

struct MapInPlaceVisitor<'a, K: 'a, V: 'a>(&'a mut AHashMap<K, V>);

impl<'a, 'de, K, V> Visitor<'de> for MapInPlaceVisitor<'a, K, V>
where
K: Deserialize<'de> + Eq + Hash,
V: Deserialize<'de>,
{
type Value = ();

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a map")
}

fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
self.0.clear();
self.0.reserve(map.size_hint().unwrap_or(0).min(4096));

while let Some((key, value)) = map.next_entry()? {
self.0.insert(key, value);
}

Ok(())
}
}

deserializer.deserialize_map(MapInPlaceVisitor(place))
}
}

#[cfg(test)]
Expand All @@ -382,8 +416,14 @@ mod test {
let mut map = AHashMap::new();
map.insert("for".to_string(), 0);
map.insert("bar".to_string(), 1);
let serialization = serde_json::to_string(&map).unwrap();
let deserialization: AHashMap<String, u64> = serde_json::from_str(&serialization).unwrap();
let mut serialization = serde_json::to_string(&map).unwrap();
let mut deserialization: AHashMap<String, u64> = serde_json::from_str(&serialization).unwrap();
assert_eq!(deserialization, map);

map.insert("baz".to_string(), 2);
serialization = serde_json::to_string(&map).unwrap();
let mut deserializer = serde_json::Deserializer::from_str(&serialization);
AHashMap::deserialize_in_place(&mut deserializer, &mut deserialization).unwrap();
assert_eq!(deserialization, map);
}
}
14 changes: 12 additions & 2 deletions src/hash_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@ where
let hash_set = HashSet::deserialize(deserializer);
hash_set.map(|hash_set| Self(hash_set))
}

fn deserialize_in_place<D: Deserializer<'de>>(deserializer: D, place: &mut Self) -> Result<(), D::Error> {
HashSet::deserialize_in_place(deserializer, place)
}
}

#[cfg(all(test, feature = "serde"))]
Expand All @@ -324,8 +328,14 @@ mod test {
let mut set = AHashSet::new();
set.insert("for".to_string());
set.insert("bar".to_string());
let serialization = serde_json::to_string(&set).unwrap();
let deserialization: AHashSet<String> = serde_json::from_str(&serialization).unwrap();
let mut serialization = serde_json::to_string(&set).unwrap();
let mut deserialization: AHashSet<String> = serde_json::from_str(&serialization).unwrap();
assert_eq!(deserialization, set);

set.insert("baz".to_string());
serialization = serde_json::to_string(&set).unwrap();
let mut deserializer = serde_json::Deserializer::from_str(&serialization);
AHashSet::deserialize_in_place(&mut deserializer, &mut deserialization).unwrap();
assert_eq!(deserialization, set);
}
}

0 comments on commit f2aecc0

Please sign in to comment.