Skip to content

Commit

Permalink
Add tests for IndexMap and IndexSet
Browse files Browse the repository at this point in the history
During the tests a missing implementation of `DuplicateInsertsFirstWinsMap`
was noticed, but is now included.
`indexmap` was also missing the `serde-1` feature flag.
  • Loading branch information
jonasbb committed Apr 19, 2022
1 parent a8bce82 commit 82a5d18
Show file tree
Hide file tree
Showing 5 changed files with 340 additions and 5 deletions.
7 changes: 6 additions & 1 deletion serde_with/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ base64_crate = {package = "base64", version = "0.13.0", optional = true}
chrono_crate = {package = "chrono", version = "0.4.1", features = ["clock", "serde", "std"], optional = true, default-features = false}
doc-comment = {version = "0.3.3", optional = true}
hex = {version = "0.4.2", optional = true}
indexmap_crate = {package = "indexmap", version = "1.8", optional = true}
indexmap_crate = {package = "indexmap", version = "1.8", features = ["serde-1"], optional = true}
rustversion = "1.0.0"
serde = {version = "1.0.122", features = ["derive"]}
serde_json = {version = "1.0.1", optional = true}
Expand Down Expand Up @@ -75,6 +75,11 @@ name = "hex"
path = "tests/hex.rs"
required-features = ["hex", "macros"]

[[test]]
name = "indexmap"
path = "tests/indexmap.rs"
required-features = ["indexmap", "macros"]

[[test]]
name = "json"
path = "tests/json.rs"
Expand Down
25 changes: 21 additions & 4 deletions serde_with/src/de/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::formats::{Flexible, Format, Strict};
use crate::rust::StringWithSeparator;
use crate::utils;
use crate::utils::duration::DurationSigned;
#[cfg(feature = "indexmap")]
use indexmap_crate::{IndexMap, IndexSet};
use serde::de::*;
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -312,8 +314,15 @@ seq_impl!(
VecDeque::with_capacity(utils::size_hint_cautious(seq.size_hint())),
push_back
);
#[cfg(feature = "indexmap")]
seq_impl!(
IndexSet<T: Eq + Hash, S: BuildHasher + Default>,
seq,
IndexSet::with_capacity_and_hasher(utils::size_hint_cautious(seq.size_hint()), S::default()),
insert
);

macro_rules! map_impl2 {
macro_rules! map_impl {
(
$ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
// We need an external name, such that we can use it in the `with_capacity` expression
Expand Down Expand Up @@ -375,15 +384,19 @@ macro_rules! map_impl2 {
}
}

map_impl2!(
map_impl!(
BTreeMap<K: Ord, V>,
map,
BTreeMap::new());

map_impl2!(
map_impl!(
HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
map,
HashMap::with_capacity_and_hasher(utils::size_hint_cautious(map.size_hint()), S::default()));
#[cfg(feature = "indexmap")]
map_impl!(
IndexMap<K: Eq + Hash, V, S: BuildHasher + Default>,
map,
IndexMap::with_capacity_and_hasher(utils::size_hint_cautious(map.size_hint()), S::default()));

macro_rules! tuple_impl {
($len:literal $($n:tt $t:ident $tas:ident)+) => {
Expand Down Expand Up @@ -505,6 +518,8 @@ macro_rules! map_as_tuple_seq {
}
map_as_tuple_seq!(BTreeMap<K: Ord, V>);
map_as_tuple_seq!(HashMap<K: Eq + Hash, V>);
#[cfg(feature = "indexmap")]
map_as_tuple_seq!(IndexMap<K: Eq + Hash, V>);

// endregion
///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -680,6 +695,8 @@ tuple_seq_as_map_impl! {
Vec<(K, V)>,
VecDeque<(K, V)>,
}
#[cfg(feature = "indexmap")]
tuple_seq_as_map_impl!(IndexSet<(K: Eq + Hash, V: Eq + Hash)>);

macro_rules! tuple_seq_as_map_option_impl {
($($ty:ident $(,)?)+) => {$(
Expand Down
30 changes: 30 additions & 0 deletions serde_with/src/duplicate_key_impls/first_value_wins.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[cfg(feature = "indexmap")]
use indexmap_crate::IndexMap;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::{BuildHasher, Hash};

Expand Down Expand Up @@ -81,6 +83,34 @@ where
}
}

#[cfg(feature = "indexmap")]
impl<K, V, S> DuplicateInsertsFirstWinsMap<K, V> for IndexMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher + Default,
{
#[inline]
fn new(size_hint: Option<usize>) -> Self {
match size_hint {
Some(size) => Self::with_capacity_and_hasher(size, S::default()),
None => Self::with_hasher(S::default()),
}
}

#[inline]
fn insert(&mut self, key: K, value: V) {
use indexmap_crate::map::Entry;

match self.entry(key) {
// we want to keep the first value, so do nothing
Entry::Occupied(_) => {}
Entry::Vacant(vacant) => {
vacant.insert(value);
}
}
}
}

impl<K, V> DuplicateInsertsFirstWinsMap<K, V> for BTreeMap<K, V>
where
K: Ord,
Expand Down
11 changes: 11 additions & 0 deletions serde_with/src/ser/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use crate::formats::Strictness;
use crate::rust::StringWithSeparator;
use crate::utils::duration::DurationSigned;
use crate::Separator;
#[cfg(feature = "indexmap")]
use indexmap_crate::{IndexMap, IndexSet};
use serde::ser::Error;
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
Expand Down Expand Up @@ -228,6 +230,8 @@ seq_impl!(LinkedList<T>);
seq_impl!(Slice<T>);
seq_impl!(Vec<T>);
seq_impl!(VecDeque<T>);
#[cfg(feature = "indexmap")]
seq_impl!(IndexSet<T, H: Sized>);

macro_rules! map_impl {
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
Expand All @@ -250,6 +254,8 @@ macro_rules! map_impl {

map_impl!(BTreeMap<K, V>);
map_impl!(HashMap<K, V, H: Sized>);
#[cfg(feature = "indexmap")]
map_impl!(IndexMap<K, V, H: Sized>);

macro_rules! tuple_impl {
($len:literal $($n:tt $t:ident $tas:ident)+) => {
Expand Down Expand Up @@ -311,7 +317,10 @@ macro_rules! map_as_tuple_seq {
};
}
map_as_tuple_seq!(BTreeMap<K, V>);
// TODO HashMap with a custom hasher support would be better, but results in "unconstrained type parameter"
map_as_tuple_seq!(HashMap<K, V>);
#[cfg(feature = "indexmap")]
map_as_tuple_seq!(IndexMap<K, V>);

// endregion
///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -403,6 +412,8 @@ tuple_seq_as_map_impl! {
Vec<(K, V)>,
VecDeque<(K, V)>,
}
#[cfg(feature = "indexmap")]
tuple_seq_as_map_impl!(IndexSet<(K, V)>);

impl<T, TAs> SerializeAs<T> for DefaultOnError<TAs>
where
Expand Down
Loading

0 comments on commit 82a5d18

Please sign in to comment.