Skip to content

Commit f5137b6

Browse files
bors[bot]jonasbb
andauthored
Merge #627
627: Add trait implementations for indexmap v2 r=jonasbb a=jonasbb Introduces a new feature flag `indexmap_2` that enables the support. Tests are copied from the v1 support. Closes #621 Co-authored-by: Jonas Bushart <[email protected]>
2 parents a8d2498 + f46b369 commit f5137b6

File tree

15 files changed

+447
-23
lines changed

15 files changed

+447
-23
lines changed

.github/workflows/ci.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
# It is good to test more than the MSRV and stable since sometimes
6262
# breakage occurs in intermediate versions.
6363
# IMPORTANT: Synchronize the MSRV with the Cargo.toml values.
64-
rust: ["1.61", "1.65", "1.70", "stable", "beta", "nightly"]
64+
rust: ["1.64", "1.65", "1.70", "stable", "beta", "nightly"]
6565
runs-on: ${{ matrix.os }}
6666
steps:
6767
- uses: actions/checkout@v3

Cargo.lock

+28-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

serde_with/CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10+
### Added
11+
12+
* Add optional support for indexmap v2 (#621)
13+
Support for v1 is already available using the `indexmap_1` feature.
14+
This adds identical support for v2 of indexmap using the `indexmap_2` feature.
15+
16+
### Changed
17+
18+
* Bump MSRV to 1.64, since that is required for the indexmap v2 dependency.
19+
1020
## [3.1.0] - 2023-07-17
1121

1222
### Added

serde_with/Cargo.toml

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ authors = [
55
"Marcin Kaźmierczak",
66
]
77
name = "serde_with"
8-
rust-version = "1.61"
8+
rust-version = "1.64"
99
version = "3.1.0"
1010

1111
categories = ["encoding", "no-std", "no-std::no-alloc"]
@@ -43,6 +43,7 @@ std = [
4343
"chrono_0_4?/clock",
4444
"chrono_0_4?/std",
4545
"indexmap_1?/std",
46+
"indexmap_2?/std",
4647
"time_0_3?/serde-well-known",
4748
"time_0_3?/std",
4849
]
@@ -54,6 +55,7 @@ guide = ["dep:doc-comment", "macros", "std"]
5455
hex = ["dep:hex", "alloc"]
5556
indexmap = ["indexmap_1"]
5657
indexmap_1 = ["dep:indexmap_1", "alloc"]
58+
indexmap_2 = ["dep:indexmap_2", "alloc"]
5759
json = ["dep:serde_json", "alloc"]
5860
macros = ["dep:serde_with_macros"]
5961
time_0_3 = ["dep:time_0_3"]
@@ -65,6 +67,7 @@ chrono_0_4 = {package = "chrono", version = "0.4.20", optional = true, default-f
6567
doc-comment = {version = "0.3.3", optional = true}
6668
hex = {version = "0.4.3", optional = true, default-features = false}
6769
indexmap_1 = {package = "indexmap", version = "1.8", optional = true, default-features = false, features = ["serde-1"]}
70+
indexmap_2 = {package = "indexmap", version = "2.0", optional = true, default-features = false, features = ["serde"]}
6871
# The derive feature is needed for the flattened_maybe macro.
6972
# https://github.com/jonasbb/serde_with/blob/eb1965a74a3be073ecd13ec05f02a01bc1c44309/serde_with/src/flatten_maybe.rs#L67
7073
serde = {version = "1.0.157", default-features = false, features = ["derive"] }
@@ -113,6 +116,11 @@ name = "indexmap_1"
113116
path = "tests/indexmap_1.rs"
114117
required-features = ["indexmap_1", "macros"]
115118

119+
[[test]]
120+
name = "indexmap_2"
121+
path = "tests/indexmap_2.rs"
122+
required-features = ["indexmap_2", "macros"]
123+
116124
[[test]]
117125
name = "json"
118126
path = "tests/json.rs"

serde_with/src/de/duplicates.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::{
99
};
1010
#[cfg(feature = "indexmap_1")]
1111
use indexmap_1::{IndexMap, IndexSet};
12+
#[cfg(feature = "indexmap_2")]
13+
use indexmap_2::{IndexMap as IndexMap2, IndexSet as IndexSet2};
1214

1315
struct SetPreventDuplicatesVisitor<SET, T, TAs>(PhantomData<(SET, T, TAs)>);
1416

serde_with/src/de/impls.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::{formats::*, prelude::*};
22
#[cfg(feature = "indexmap_1")]
33
use indexmap_1::{IndexMap, IndexSet};
4+
#[cfg(feature = "indexmap_2")]
5+
use indexmap_2::{IndexMap as IndexMap2, IndexSet as IndexSet2};
46

57
///////////////////////////////////////////////////////////////////////////////
68
// Helper macro used internally
@@ -16,6 +18,8 @@ macro_rules! foreach_map {
1618
$m!(HashMap<K: Eq + Hash, V, H: Sized>);
1719
#[cfg(all(feature = "std", feature = "indexmap_1"))]
1820
$m!(IndexMap<K: Eq + Hash, V, H: Sized>);
21+
#[cfg(all(feature = "std", feature = "indexmap_2"))]
22+
$m!(IndexMap2<K: Eq + Hash, V, H: Sized>);
1923
};
2024
}
2125
pub(crate) use foreach_map;
@@ -34,6 +38,11 @@ macro_rules! foreach_map_create {
3438
IndexMap<K: Eq + Hash, V, S: BuildHasher + Default>,
3539
(|size| IndexMap::with_capacity_and_hasher(size, Default::default()))
3640
);
41+
#[cfg(feature = "indexmap_2")]
42+
$m!(
43+
IndexMap2<K: Eq + Hash, V, S: BuildHasher + Default>,
44+
(|size| IndexMap2::with_capacity_and_hasher(size, Default::default()))
45+
);
3746
};
3847
}
3948
pub(crate) use foreach_map_create;
@@ -46,6 +55,8 @@ macro_rules! foreach_set {
4655
$m!(HashSet<(K, V): Eq + Hash>);
4756
#[cfg(all(feature = "std", feature = "indexmap_1"))]
4857
$m!(IndexSet<(K, V): Eq + Hash>);
58+
#[cfg(all(feature = "std", feature = "indexmap_2"))]
59+
$m!(IndexSet2<(K, V): Eq + Hash>);
4960
}
5061
}
5162
pub(crate) use foreach_set;
@@ -66,6 +77,12 @@ macro_rules! foreach_set_create {
6677
(|size| IndexSet::with_capacity_and_hasher(size, S::default())),
6778
insert
6879
);
80+
#[cfg(feature = "indexmap_2")]
81+
$m!(
82+
IndexSet2<T: Eq + Hash, S: BuildHasher + Default>,
83+
(|size| IndexSet2::with_capacity_and_hasher(size, S::default())),
84+
insert
85+
);
6986
};
7087
}
7188
pub(crate) use foreach_set_create;

serde_with/src/duplicate_key_impls/error_on_duplicate.rs

+42-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use crate::prelude::*;
2-
#[cfg(feature = "indexmap_1")]
3-
use indexmap_1::{IndexMap, IndexSet};
42

53
pub trait PreventDuplicateInsertsSet<T> {
64
fn new(size_hint: Option<usize>) -> Self;
@@ -37,7 +35,27 @@ where
3735
}
3836

3937
#[cfg(feature = "indexmap_1")]
40-
impl<T, S> PreventDuplicateInsertsSet<T> for IndexSet<T, S>
38+
impl<T, S> PreventDuplicateInsertsSet<T> for indexmap_1::IndexSet<T, S>
39+
where
40+
T: Eq + Hash,
41+
S: BuildHasher + Default,
42+
{
43+
#[inline]
44+
fn new(size_hint: Option<usize>) -> Self {
45+
match size_hint {
46+
Some(size) => Self::with_capacity_and_hasher(size, S::default()),
47+
None => Self::with_hasher(S::default()),
48+
}
49+
}
50+
51+
#[inline]
52+
fn insert(&mut self, value: T) -> bool {
53+
self.insert(value)
54+
}
55+
}
56+
57+
#[cfg(feature = "indexmap_2")]
58+
impl<T, S> PreventDuplicateInsertsSet<T> for indexmap_2::IndexSet<T, S>
4159
where
4260
T: Eq + Hash,
4361
S: BuildHasher + Default,
@@ -92,7 +110,27 @@ where
92110
}
93111

94112
#[cfg(feature = "indexmap_1")]
95-
impl<K, V, S> PreventDuplicateInsertsMap<K, V> for IndexMap<K, V, S>
113+
impl<K, V, S> PreventDuplicateInsertsMap<K, V> for indexmap_1::IndexMap<K, V, S>
114+
where
115+
K: Eq + Hash,
116+
S: BuildHasher + Default,
117+
{
118+
#[inline]
119+
fn new(size_hint: Option<usize>) -> Self {
120+
match size_hint {
121+
Some(size) => Self::with_capacity_and_hasher(size, S::default()),
122+
None => Self::with_hasher(S::default()),
123+
}
124+
}
125+
126+
#[inline]
127+
fn insert(&mut self, key: K, value: V) -> bool {
128+
self.insert(key, value).is_none()
129+
}
130+
}
131+
132+
#[cfg(feature = "indexmap_2")]
133+
impl<K, V, S> PreventDuplicateInsertsMap<K, V> for indexmap_2::IndexMap<K, V, S>
96134
where
97135
K: Eq + Hash,
98136
S: BuildHasher + Default,

serde_with/src/duplicate_key_impls/first_value_wins.rs

+29-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use crate::prelude::*;
2-
#[cfg(feature = "indexmap_1")]
3-
use indexmap_1::IndexMap;
42

53
pub trait DuplicateInsertsFirstWinsMap<K, V> {
64
fn new(size_hint: Option<usize>) -> Self;
@@ -38,7 +36,7 @@ where
3836
}
3937

4038
#[cfg(feature = "indexmap_1")]
41-
impl<K, V, S> DuplicateInsertsFirstWinsMap<K, V> for IndexMap<K, V, S>
39+
impl<K, V, S> DuplicateInsertsFirstWinsMap<K, V> for indexmap_1::IndexMap<K, V, S>
4240
where
4341
K: Eq + Hash,
4442
S: BuildHasher + Default,
@@ -65,6 +63,34 @@ where
6563
}
6664
}
6765

66+
#[cfg(feature = "indexmap_2")]
67+
impl<K, V, S> DuplicateInsertsFirstWinsMap<K, V> for indexmap_2::IndexMap<K, V, S>
68+
where
69+
K: Eq + Hash,
70+
S: BuildHasher + Default,
71+
{
72+
#[inline]
73+
fn new(size_hint: Option<usize>) -> Self {
74+
match size_hint {
75+
Some(size) => Self::with_capacity_and_hasher(size, S::default()),
76+
None => Self::with_hasher(S::default()),
77+
}
78+
}
79+
80+
#[inline]
81+
fn insert(&mut self, key: K, value: V) {
82+
use indexmap_2::map::Entry;
83+
84+
match self.entry(key) {
85+
// we want to keep the first value, so do nothing
86+
Entry::Occupied(_) => {}
87+
Entry::Vacant(vacant) => {
88+
vacant.insert(value);
89+
}
90+
}
91+
}
92+
}
93+
6894
impl<K, V> DuplicateInsertsFirstWinsMap<K, V> for BTreeMap<K, V>
6995
where
7096
K: Ord,

serde_with/src/duplicate_key_impls/last_value_wins.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use crate::prelude::*;
2-
#[cfg(feature = "indexmap_1")]
3-
use indexmap_1::IndexSet;
42

53
pub trait DuplicateInsertsLastWinsSet<T> {
64
fn new(size_hint: Option<usize>) -> Self;
@@ -31,7 +29,28 @@ where
3129
}
3230

3331
#[cfg(feature = "indexmap_1")]
34-
impl<T, S> DuplicateInsertsLastWinsSet<T> for IndexSet<T, S>
32+
impl<T, S> DuplicateInsertsLastWinsSet<T> for indexmap_1::IndexSet<T, S>
33+
where
34+
T: Eq + Hash,
35+
S: BuildHasher + Default,
36+
{
37+
#[inline]
38+
fn new(size_hint: Option<usize>) -> Self {
39+
match size_hint {
40+
Some(size) => Self::with_capacity_and_hasher(size, S::default()),
41+
None => Self::with_hasher(S::default()),
42+
}
43+
}
44+
45+
#[inline]
46+
fn replace(&mut self, value: T) {
47+
// Hashset already fulfils the contract
48+
self.replace(value);
49+
}
50+
}
51+
52+
#[cfg(feature = "indexmap_2")]
53+
impl<T, S> DuplicateInsertsLastWinsSet<T> for indexmap_2::IndexSet<T, S>
3554
where
3655
T: Eq + Hash,
3756
S: BuildHasher + Default,

serde_with/src/guide/feature_flags.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ Using it in a `no_std` environment requires using `default-features = false`, si
1313
5. [`guide`](#guide)
1414
6. [`hex`](#hex)
1515
7. [`indexmap_1`](#indexmap_1)
16-
8. [`json`](#json)
17-
9. [`macros` (default)](#macros-default)
18-
10. [`time_0_3`](#time_0_3)
16+
8. [`indexmap_2`](#indexmap_2)
17+
9. [`json`](#json)
18+
10. [`macros` (default)](#macros-default)
19+
11. [`time_0_3`](#time_0_3)
1920

2021
## `alloc`
2122

@@ -57,11 +58,20 @@ It enables the `alloc` feature.
5758

5859
## `indexmap_1`
5960

60-
The `indexmap_1` feature enables implementations of `indexmap_1` specific checks.
61+
The `indexmap_1` feature enables implementations of `indexmap` v1 specific checks.
6162
This includes support for checking duplicate keys and duplicate values.
6263
The legacy feature name `indexmap` is still available for v1 compatability.
6364

64-
This pulls in `indexmap` as a dependency.
65+
This pulls in `indexmap` v1 as a dependency.
66+
It enables the `alloc` feature.
67+
Some functionality is only available when `std` is enabled too.
68+
69+
## `indexmap_2`
70+
71+
The `indexmap_2` feature enables implementations of `indexmap` v2 specific checks.
72+
This includes support for checking duplicate keys and duplicate values.
73+
74+
This pulls in `indexmap` v2 as a dependency.
6575
It enables the `alloc` feature.
6676
Some functionality is only available when `std` is enabled too.
6777

0 commit comments

Comments
 (0)