Skip to content

Commit

Permalink
feat: Add support for HashMap<K, V, S> (for other S)
Browse files Browse the repository at this point in the history
This makes the implementations for Serialize and JsonSerialize
accept different S values instead of the default RandomState
specified by `std::collections::HashMap`.

It also adds an example with the ahash crate.

Closes #87
  • Loading branch information
fasterthanlime committed Oct 6, 2024
1 parent 65c5c75 commit d3191ae
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
pushd merde
EXAMPLES=($(cd examples && for i in *; do echo "${i%.rs}"; done))
for example in "${EXAMPLES[@]}"; do
cargo run --features full --example "$example"
cargo run --features full,json --example "$example"
done
popd
- name: Test zerodeps-example
Expand Down
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ check:
pushd merde
EXAMPLES=($(cd examples && for i in *; do echo "${i%.rs}"; done))
for example in "${EXAMPLES[@]}"; do
cargo run --features full --example "$example"
cargo run --features full,ahash --example "$example"
done
popd
9 changes: 9 additions & 0 deletions merde/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ name = "yaml"
path = "examples/yaml.rs"
required-features = ["yaml"]

[[example]]
name = "ahash"
path = "examples/ahash.rs"
required-features = ["json", "ahash"]

[dependencies]
merde_core = { version = "6.0.2", path = "../merde_core", optional = true }
merde_json = { version = "6.0.3", path = "../merde_json", optional = true }
Expand All @@ -48,6 +53,7 @@ merde_time = { version = "4.0.14", path = "../merde_time", optional = true, feat
"merde",
"deserialize",
] }
ahash = { version = "0.8.11", optional = true }

[features]
default = ["core", "deserialize"]
Expand All @@ -71,3 +77,6 @@ rusqlite = ["merde_core/rusqlite"]
json = ["dep:merde_json", "merde_time/json"]
yaml = ["dep:merde_yaml"]
time = ["dep:merde_time"]

# others
ahash = ["dep:ahash"]
26 changes: 26 additions & 0 deletions merde/examples/ahash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#[cfg(feature = "ahash")]
fn main() {
use ahash::HashMap;
use merde::json;

let mut h = HashMap::default();
h.insert("street".to_string(), "123 Main St".to_string());
h.insert("city".to_string(), "Anytown".to_string());
h.insert("state".to_string(), "CA".to_string());
h.insert("zip".to_string(), "12345".to_string());

println!("h: {:#?}", h);

let serialized = json::to_string(&h);
println!("serialized: {}", serialized);

let deserialized: HashMap<String, String> = json::from_str(&serialized).unwrap();
println!("deserialized: {:#?}", deserialized);

assert_eq!(h, deserialized);

assert_eq!(deserialized.get("street"), Some(&"123 Main St".to_string()));
assert_eq!(deserialized.get("city"), Some(&"Anytown".to_string()));
assert_eq!(deserialized.get("state"), Some(&"CA".to_string()));
assert_eq!(deserialized.get("zip"), Some(&"12345".to_string()));
}
9 changes: 6 additions & 3 deletions merde_core/src/deserialize.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::{
borrow::Cow,
collections::HashMap,
future::Future,
hash::{BuildHasher, Hash},
pin::Pin,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
Expand Down Expand Up @@ -470,17 +472,18 @@ impl<'s, T: Deserialize<'s>> Deserialize<'s> for Vec<T> {
}
}

impl<'s, K, V> Deserialize<'s> for std::collections::HashMap<K, V>
impl<'s, K, V, S> Deserialize<'s> for HashMap<K, V, S>
where
K: Deserialize<'s> + Eq + std::hash::Hash,
K: Deserialize<'s> + Eq + Hash,
V: Deserialize<'s>,
S: Default + BuildHasher + 's,
{
async fn deserialize<D>(de: &mut D) -> Result<Self, D::Error<'s>>
where
D: Deserializer<'s> + ?Sized,
{
de.next()?.into_map_start()?;
let mut map = std::collections::HashMap::new();
let mut map = HashMap::<K, V, S>::default();

loop {
match de.next()? {
Expand Down
6 changes: 4 additions & 2 deletions merde_core/src/into_static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::borrow::Cow;
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::hash::BuildHasher;
use std::hash::Hash;

/// Allow turning a value into an "owned" variant, which can then be
Expand Down Expand Up @@ -83,13 +84,14 @@ impl<T: IntoStatic> IntoStatic for Vec<T> {
}
}

impl<K, V> IntoStatic for HashMap<K, V>
impl<K, V, S> IntoStatic for HashMap<K, V, S>
where
S: BuildHasher + Default + 'static,
K: IntoStatic + Eq + Hash,
V: IntoStatic,
K::Output: Eq + Hash,
{
type Output = HashMap<K::Output, V::Output>;
type Output = HashMap<K::Output, V::Output, S>;

fn into_static(self) -> Self::Output {
self.into_iter()
Expand Down
5 changes: 3 additions & 2 deletions merde_core/src/with_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,13 @@ where
type Lifetimed = HashSet<T::Lifetimed>;
}

impl<'s, K, V> WithLifetime<'s> for HashMap<K, V>
impl<'s, K, V, S> WithLifetime<'s> for HashMap<K, V, S>
where
S: 's,
K: WithLifetime<'s>,
V: WithLifetime<'s>,
{
type Lifetimed = HashMap<K::Lifetimed, V::Lifetimed>;
type Lifetimed = HashMap<K::Lifetimed, V::Lifetimed, S>;
}

impl<'s, T1: WithLifetime<'s>> WithLifetime<'s> for (T1,) {
Expand Down
2 changes: 1 addition & 1 deletion merde_json/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ impl JsonSerialize for bool {
}
}

impl<K: AsRef<str>, V: JsonSerialize> JsonSerialize for HashMap<K, V> {
impl<K: AsRef<str>, V: JsonSerialize, S> JsonSerialize for HashMap<K, V, S> {
fn json_serialize(&self, serializer: &mut JsonSerializer) {
let mut guard = serializer.write_obj();
for (key, value) in self {
Expand Down

0 comments on commit d3191ae

Please sign in to comment.