From 0ceb9d84fa3777d95f263da9c9a65c74bf76795e Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Mon, 19 Aug 2024 21:39:10 +0100 Subject: [PATCH 1/2] Add `OccupiedEntry::remove_entry()` (and shift/swap versions) --- src/map.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/map.rs b/src/map.rs index 3ffff15f8..d63d1a60c 100644 --- a/src/map.rs +++ b/src/map.rs @@ -900,6 +900,69 @@ impl<'a> OccupiedEntry<'a> { #[cfg(not(feature = "preserve_order"))] return self.occupied.remove(); } + + /// Removes the entry from the map, returning the stored key and value. + /// + /// If serde_json's "preserve_order" is enabled, `.remove_entry()` is + /// equivalent to [`.swap_remove_entry()`][Self::swap_remove_entry], + /// replacing this entry's position with the last element. If you need to + /// preserve the relative order of the keys in the map, use + /// [`.shift_remove_entry()`][Self::shift_remove_entry] instead. + /// + /// # Examples + /// + /// ``` + /// # use serde_json::json; + /// # + /// use serde_json::map::Entry; + /// + /// let mut map = serde_json::Map::new(); + /// map.insert("serde".to_owned(), json!(12)); + /// + /// match map.entry("serde") { + /// Entry::Occupied(occupied) => { + /// let (key, value) = occupied.remove_entry(); + /// assert_eq!(key, "serde"); + /// assert_eq!(value, 12); + /// } + /// Entry::Vacant(_) => unimplemented!(), + /// } + /// ``` + #[inline] + pub fn remove_entry(self) -> (String, Value) { + #[cfg(feature = "preserve_order")] + return self.swap_remove_entry(); + #[cfg(not(feature = "preserve_order"))] + return self.occupied.remove_entry(); + } + + /// Removes the entry from the map, returning the stored key and value. + /// + /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the + /// last element of the map and popping it off. This perturbs the position + /// of what used to be the last element! + /// + /// [`Vec::swap_remove`]: std::vec::Vec::swap_remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn swap_remove_entry(self) -> (String, Value) { + self.occupied.swap_remove_entry() + } + + /// Removes the entry from the map, returning the stored key and value. + /// + /// Like [`Vec::remove`], the entry is removed by shifting all of the + /// elements that follow it, preserving their relative order. This perturbs + /// the index of all of those elements! + /// + /// [`Vec::remove`]: std::vec::Vec::remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn shift_remove_entry(self) -> (String, Value) { + self.occupied.shift_remove_entry() + } } ////////////////////////////////////////////////////////////////////////////// From 11fc61c7af7b59ea80fb2ef7d78db94465dfbd54 Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Mon, 19 Aug 2024 21:43:12 +0100 Subject: [PATCH 2/2] Add `OccupiedEntry::shift_remove()` and `swap_remove()` --- src/map.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/map.rs b/src/map.rs index d63d1a60c..61864c3c2 100644 --- a/src/map.rs +++ b/src/map.rs @@ -876,6 +876,12 @@ impl<'a> OccupiedEntry<'a> { /// Takes the value of the entry out of the map, and returns it. /// + /// If serde_json's "preserve_order" is enabled, `.remove()` is + /// equivalent to [`.swap_remove()`][Self::swap_remove], replacing this + /// entry's position with the last element. If you need to preserve the + /// relative order of the keys in the map, use + /// [`.shift_remove()`][Self::shift_remove] instead. + /// /// # Examples /// /// ``` @@ -896,11 +902,39 @@ impl<'a> OccupiedEntry<'a> { #[inline] pub fn remove(self) -> Value { #[cfg(feature = "preserve_order")] - return self.occupied.swap_remove(); + return self.swap_remove(); #[cfg(not(feature = "preserve_order"))] return self.occupied.remove(); } + /// Takes the value of the entry out of the map, and returns it. + /// + /// Like [`Vec::remove`], the entry is removed by shifting all of the + /// elements that follow it, preserving their relative order. This perturbs + /// the index of all of those elements! + /// + /// [`Vec::remove`]: std::vec::Vec::remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn shift_remove(self) -> Value { + self.occupied.shift_remove() + } + + /// Takes the value of the entry out of the map, and returns it. + /// + /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the + /// last element of the map and popping it off. This perturbs the position + /// of what used to be the last element! + /// + /// [`Vec::swap_remove`]: std::vec::Vec::swap_remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn swap_remove(self) -> Value { + self.occupied.swap_remove() + } + /// Removes the entry from the map, returning the stored key and value. /// /// If serde_json's "preserve_order" is enabled, `.remove_entry()` is