Skip to content

Commit 5aeab4e

Browse files
authored
Merge pull request #1109 from serde-rs/remove
Add swap_remove and shift_remove methods on Map
2 parents 7fece96 + ca3c2ca commit 5aeab4e

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ repository = "https://github.com/serde-rs/json"
1212
rust-version = "1.56"
1313

1414
[dependencies]
15-
indexmap = { version = "2", optional = true }
15+
indexmap = { version = "2.2.1", optional = true }
1616
itoa = "1.0"
1717
ryu = "1.0"
1818
serde = { version = "1.0.194", default-features = false }
@@ -32,7 +32,7 @@ trybuild = { version = "1.0.81", features = ["diff"] }
3232
doc-scrape-examples = false
3333

3434
[package.metadata.docs.rs]
35-
features = ["raw_value", "unbounded_depth"]
35+
features = ["preserve_order", "raw_value", "unbounded_depth"]
3636
targets = ["x86_64-unknown-linux-gnu"]
3737
rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"]
3838

src/map.rs

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,20 @@ impl Map<String, Value> {
130130
///
131131
/// The key may be any borrowed form of the map's key type, but the ordering
132132
/// on the borrowed form *must* match the ordering on the key type.
133+
///
134+
/// If serde_json's "preserve_order" is enabled, `.remove(key)` is
135+
/// equivalent to [`.swap_remove(key)`][Self::swap_remove], replacing this
136+
/// entry's position with the last element. If you need to preserve the
137+
/// relative order of the keys in the map, use
138+
/// [`.shift_remove(key)`][Self::shift_remove] instead.
133139
#[inline]
134140
pub fn remove<Q>(&mut self, key: &Q) -> Option<Value>
135141
where
136142
String: Borrow<Q>,
137143
Q: ?Sized + Ord + Eq + Hash,
138144
{
139145
#[cfg(feature = "preserve_order")]
140-
return self.map.swap_remove(key);
146+
return self.swap_remove(key);
141147
#[cfg(not(feature = "preserve_order"))]
142148
return self.map.remove(key);
143149
}
@@ -147,12 +153,86 @@ impl Map<String, Value> {
147153
///
148154
/// The key may be any borrowed form of the map's key type, but the ordering
149155
/// on the borrowed form *must* match the ordering on the key type.
156+
///
157+
/// If serde_json's "preserve_order" is enabled, `.remove_entry(key)` is
158+
/// equivalent to [`.swap_remove_entry(key)`][Self::swap_remove_entry],
159+
/// replacing this entry's position with the last element. If you need to
160+
/// preserve the relative order of the keys in the map, use
161+
/// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
162+
#[inline]
150163
pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
151164
where
152165
String: Borrow<Q>,
153166
Q: ?Sized + Ord + Eq + Hash,
154167
{
155-
self.map.remove_entry(key)
168+
#[cfg(feature = "preserve_order")]
169+
return self.swap_remove_entry(key);
170+
#[cfg(not(feature = "preserve_order"))]
171+
return self.map.remove_entry(key);
172+
}
173+
174+
/// Removes and returns the value corresponding to the key from the map.
175+
///
176+
/// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
177+
/// last element of the map and popping it off. This perturbs the position
178+
/// of what used to be the last element!
179+
#[cfg(feature = "preserve_order")]
180+
#[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
181+
#[inline]
182+
pub fn swap_remove<Q>(&mut self, key: &Q) -> Option<Value>
183+
where
184+
String: Borrow<Q>,
185+
Q: ?Sized + Ord + Eq + Hash,
186+
{
187+
self.map.swap_remove(key)
188+
}
189+
190+
/// Remove and return the key-value pair.
191+
///
192+
/// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
193+
/// last element of the map and popping it off. This perturbs the position
194+
/// of what used to be the last element!
195+
#[cfg(feature = "preserve_order")]
196+
#[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
197+
#[inline]
198+
pub fn swap_remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
199+
where
200+
String: Borrow<Q>,
201+
Q: ?Sized + Ord + Eq + Hash,
202+
{
203+
self.map.swap_remove_entry(key)
204+
}
205+
206+
/// Removes and returns the value corresponding to the key from the map.
207+
///
208+
/// Like [`Vec::remove`], the entry is removed by shifting all of the
209+
/// elements that follow it, preserving their relative order. This perturbs
210+
/// the index of all of those elements!
211+
#[cfg(feature = "preserve_order")]
212+
#[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
213+
#[inline]
214+
pub fn shift_remove<Q>(&mut self, key: &Q) -> Option<Value>
215+
where
216+
String: Borrow<Q>,
217+
Q: ?Sized + Ord + Eq + Hash,
218+
{
219+
self.map.shift_remove(key)
220+
}
221+
222+
/// Remove and return the key-value pair.
223+
///
224+
/// Like [`Vec::remove`], the entry is removed by shifting all of the
225+
/// elements that follow it, preserving their relative order. This perturbs
226+
/// the index of all of those elements!
227+
#[cfg(feature = "preserve_order")]
228+
#[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))]
229+
#[inline]
230+
pub fn shift_remove_entry<Q>(&mut self, key: &Q) -> Option<(String, Value)>
231+
where
232+
String: Borrow<Q>,
233+
Q: ?Sized + Ord + Eq + Hash,
234+
{
235+
self.map.shift_remove_entry(key)
156236
}
157237

158238
/// Moves all elements from other into self, leaving other empty.

0 commit comments

Comments
 (0)