diff --git a/build.rs b/build.rs index 04ff4a0a1..e9ec7d56a 100644 --- a/build.rs +++ b/build.rs @@ -31,6 +31,12 @@ fn main() { if minor < 45 { println!("cargo:rustc-cfg=no_btreemap_remove_entry"); } + + // BTreeMap::retain + // https://blog.rust-lang.org/2021/06/17/Rust-1.53.0.html#stabilized-apis + if minor < 53 { + println!("cargo:rustc-cfg=no_btreemap_retain"); + } } fn rustc_minor_version() -> Option { diff --git a/src/map.rs b/src/map.rs index 716f12852..5ab4a39c6 100644 --- a/src/map.rs +++ b/src/map.rs @@ -234,6 +234,19 @@ impl Map { } } + #[cfg(not(no_btreemap_retain))] + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. + /// The elements are visited in ascending key order. + #[inline] + pub fn retain(&mut self, f: F) + where + F: FnMut(&String, &mut Value) -> bool, + { + self.map.retain(f); + } + /// Gets an iterator over the values of the map. #[inline] pub fn values(&self) -> Values { diff --git a/tests/map.rs b/tests/map.rs index 387a72cdd..adf00623f 100644 --- a/tests/map.rs +++ b/tests/map.rs @@ -34,3 +34,16 @@ fn test_append() { assert_eq!(keys, EXPECTED); assert!(val.is_empty()); } + +#[cfg(not(no_btreemap_retain))] +#[test] +fn test_retain() { + const EXPECTED: &[&str] = &["a", "c"]; + + let mut v: Value = from_str(r#"{"b":null,"a":null,"c":null}"#).unwrap(); + let val = v.as_object_mut().unwrap(); + val.retain(|k, _| k.as_str() != "b"); + + let keys: Vec<_> = val.keys().collect(); + assert_eq!(keys, EXPECTED); +}