From f8a99a496836ccfa6c547af9136986d13011be98 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Jan 2024 19:03:11 -0800 Subject: [PATCH] Add swap_remove and shift_remove methods on Mapping --- Cargo.toml | 2 +- src/mapping.rs | 120 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 101 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e454ab9c..39a0a2a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ repository = "https://github.com/dtolnay/serde-yaml" rust-version = "1.64" [dependencies] -indexmap = "2" +indexmap = "2.2.1" itoa = "1.0" ryu = "1.0" serde = "1.0.195" diff --git a/src/mapping.rs b/src/mapping.rs index fe8d5097..b1341a6d 100644 --- a/src/mapping.rs +++ b/src/mapping.rs @@ -87,15 +87,65 @@ impl Mapping { } /// Removes and returns the value corresponding to the key from the map. + /// + /// This is equivalent to [`.swap_remove(index)`][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(key)`][Self::shift_remove] instead. #[inline] pub fn remove(&mut self, index: I) -> Option { - index.remove_from(self) + self.swap_remove(index) } /// Remove and return the key-value pair. + /// + /// This is equivalent to [`.swap_remove_entry(index)`][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(key)`][Self::shift_remove_entry] instead. #[inline] pub fn remove_entry(&mut self, index: I) -> Option<(Value, Value)> { - index.remove_entry_from(self) + self.swap_remove_entry(index) + } + + /// Removes and returns the value corresponding to the key from the map. + /// + /// 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! + #[inline] + pub fn swap_remove(&mut self, index: I) -> Option { + index.swap_remove_from(self) + } + + /// Remove and return the key-value pair. + /// + /// 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! + #[inline] + pub fn swap_remove_entry(&mut self, index: I) -> Option<(Value, Value)> { + index.swap_remove_entry_from(self) + } + + /// Removes and returns the value corresponding to the key from the map. + /// + /// 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! + #[inline] + pub fn shift_remove(&mut self, index: I) -> Option { + index.shift_remove_from(self) + } + + /// Remove and return the key-value pair. + /// + /// 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! + #[inline] + pub fn shift_remove_entry(&mut self, index: I) -> Option<(Value, Value)> { + index.shift_remove_entry_from(self) } /// Scan through each key-value pair in the map and keep those where the @@ -203,10 +253,16 @@ pub trait Index: private::Sealed { fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value>; #[doc(hidden)] - fn remove_from(&self, v: &mut Mapping) -> Option; + fn swap_remove_from(&self, v: &mut Mapping) -> Option; + + #[doc(hidden)] + fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; + + #[doc(hidden)] + fn shift_remove_from(&self, v: &mut Mapping) -> Option; #[doc(hidden)] - fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; + fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; } struct HashLikeValue<'a>(&'a str); @@ -239,11 +295,17 @@ impl Index for Value { fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { v.map.get_mut(self) } - fn remove_from(&self, v: &mut Mapping) -> Option { - v.map.remove(self) + fn swap_remove_from(&self, v: &mut Mapping) -> Option { + v.map.swap_remove(self) } - fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { - v.map.remove_entry(self) + fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + v.map.swap_remove_entry(self) + } + fn shift_remove_from(&self, v: &mut Mapping) -> Option { + v.map.shift_remove(self) + } + fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + v.map.shift_remove_entry(self) } } @@ -257,11 +319,17 @@ impl Index for str { fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { v.map.get_mut(&HashLikeValue(self)) } - fn remove_from(&self, v: &mut Mapping) -> Option { - v.map.remove(&HashLikeValue(self)) + fn swap_remove_from(&self, v: &mut Mapping) -> Option { + v.map.swap_remove(&HashLikeValue(self)) + } + fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + v.map.swap_remove_entry(&HashLikeValue(self)) + } + fn shift_remove_from(&self, v: &mut Mapping) -> Option { + v.map.shift_remove(&HashLikeValue(self)) } - fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { - v.map.remove_entry(&HashLikeValue(self)) + fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + v.map.shift_remove_entry(&HashLikeValue(self)) } } @@ -275,11 +343,17 @@ impl Index for String { fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { self.as_str().index_into_mut(v) } - fn remove_from(&self, v: &mut Mapping) -> Option { - self.as_str().remove_from(v) + fn swap_remove_from(&self, v: &mut Mapping) -> Option { + self.as_str().swap_remove_from(v) } - fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { - self.as_str().remove_entry_from(v) + fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + self.as_str().swap_remove_entry_from(v) + } + fn shift_remove_from(&self, v: &mut Mapping) -> Option { + self.as_str().shift_remove_from(v) + } + fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + self.as_str().shift_remove_entry_from(v) } } @@ -296,11 +370,17 @@ where fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { (**self).index_into_mut(v) } - fn remove_from(&self, v: &mut Mapping) -> Option { - (**self).remove_from(v) + fn swap_remove_from(&self, v: &mut Mapping) -> Option { + (**self).swap_remove_from(v) + } + fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + (**self).swap_remove_entry_from(v) + } + fn shift_remove_from(&self, v: &mut Mapping) -> Option { + (**self).shift_remove_from(v) } - fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { - (**self).remove_entry_from(v) + fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { + (**self).shift_remove_entry_from(v) } }