From e30d42e8fe4b64ad02e14bb18767f26f53fc1f07 Mon Sep 17 00:00:00 2001 From: Joel Galenson Date: Wed, 19 May 2021 15:39:13 -0700 Subject: Upgrade rust/crates/hashlink to 0.7.0 Test: make Change-Id: Icb994f873166a9e8b6ebe569eb171cf90e0a0778 --- .cargo_vcs_info.json | 2 +- .circleci/config.yml | 10 +-- Android.bp | 10 ++- CHANGELOG.md | 8 +++ Cargo.toml | 7 +- Cargo.toml.orig | 5 +- METADATA | 10 +-- TEST_MAPPING | 11 ++++ src/linked_hash_map.rs | 34 ++++++++++ src/linked_hash_set.rs | 10 +-- src/serde.rs | 164 +++++++++++++++++++++++++---------------------- tests/linked_hash_map.rs | 15 +++++ tests/linked_hash_set.rs | 15 +++++ tests/serde.rs | 49 ++++++++++++++ 14 files changed, 249 insertions(+), 101 deletions(-) create mode 100644 TEST_MAPPING diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 89ad255..3f828db 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "a244c741ac60333e3c37298fffdbfc1aa5f3c0d6" + "sha1": "491feb0b3f9805f7548a459ac32ab24914e12db2" } } diff --git a/.circleci/config.yml b/.circleci/config.yml index 9116b38..12fde18 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -35,17 +35,17 @@ jobs: command: cargo build --all --all-targets - run: name: Run all tests - command: cargo test --all + command: cargo test --all --all-features - run: name: Run all tests under miri command: | - cargo +nightly miri test + cargo +nightly miri test --all-features - run: name: Run all tests under sanitizers command: | - RUSTFLAGS="-Z sanitizer=address" cargo +nightly -Z build-std test --target x86_64-unknown-linux-gnu - RUSTFLAGS="-Z sanitizer=leak" cargo +nightly test -Z build-std --target x86_64-unknown-linux-gnu - RUSTFLAGS="-Z sanitizer=memory" cargo +nightly test -Z build-std --target x86_64-unknown-linux-gnu + RUSTFLAGS="-Z sanitizer=address" cargo +nightly -Z build-std test --target x86_64-unknown-linux-gnu --all-features + RUSTFLAGS="-Z sanitizer=leak" cargo +nightly test -Z build-std --target x86_64-unknown-linux-gnu --all-features + RUSTFLAGS="-Z sanitizer=memory" cargo +nightly test -Z build-std --target x86_64-unknown-linux-gnu --all-features - save_cache: paths: - /usr/local/cargo/registry diff --git a/Android.bp b/Android.bp index f365f34..1a194ac 100644 --- a/Android.bp +++ b/Android.bp @@ -1,4 +1,5 @@ // This file is generated by cargo2android.py --device --run --dependencies. +// Do not modify this file as changes will be overridden on upgrade. package { default_applicable_licenses: ["external_rust_crates_hashlink_license"], @@ -48,5 +49,10 @@ rust_library { } // dependent_library ["feature_list"] -// ahash-0.4.6 -// hashbrown-0.9.1 "ahash,default,inline-more" +// ahash-0.7.2 "folded_multiply,runtime-rng,specialize" +// cfg-if-1.0.0 +// getrandom-0.2.2 +// hashbrown-0.11.2 "ahash,default,inline-more" +// libc-0.2.94 +// once_cell-1.7.2 "alloc,race,unstable" +// version_check-0.9.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 12963ea..54c2bbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [0.7.0 +- API incompatible change: depend on hashbrown 0.11, changes re-exported types. +- Fix `LinkedHashSet::back` to take `&self` not `&mut self`. +- API incompatible change: equality tests on `LinkedHashSet` are now *ordered*, + similar to `LinkedHashMap`. +- Make the serde `Deserialize` implementations on `LinkedHashMap` and + `LinkedHashSet` generic on the `BuildHasher` type. + ## [0.6.0] - API incompatible change: depend on hashbrown 0.9, re-export renamed hashbrown::TryReserveError type. diff --git a/Cargo.toml b/Cargo.toml index 6a5a2d4..92db926 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "hashlink" -version = "0.6.0" +version = "0.7.0" authors = ["kyren "] description = "HashMap-like containers that hold their key-value pairs in a user controllable order" documentation = "https://docs.rs/hashlink" @@ -22,11 +22,14 @@ keywords = ["data-structures"] license = "MIT OR Apache-2.0" repository = "https://github.com/kyren/hashlink" [dependencies.hashbrown] -version = "0.9.0" +version = "0.11.0" [dependencies.serde] version = "1.0" optional = true +[dev-dependencies.fxhash] +version = "0.2.1" + [dev-dependencies.serde_test] version = "1.0" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 6ad661b..c6de186 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "hashlink" -version = "0.6.0" +version = "0.7.0" authors = ["kyren "] edition = "2018" description = "HashMap-like containers that hold their key-value pairs in a user controllable order" @@ -17,8 +17,9 @@ circle-ci = { repository = "kyren/hashlink", branch = "master" } serde_impl = ["serde"] [dependencies] -hashbrown = "0.9.0" +hashbrown = "0.11.0" serde = { version = "1.0", optional = true } [dev-dependencies] serde_test = "1.0" +fxhash = "0.2.1" diff --git a/METADATA b/METADATA index d38b627..1aeaa1e 100644 --- a/METADATA +++ b/METADATA @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/hashlink/hashlink-0.6.0.crate" + value: "https://static.crates.io/crates/hashlink/hashlink-0.7.0.crate" } - version: "0.6.0" + version: "0.7.0" license_type: NOTICE last_upgrade_date { - year: 2020 - month: 11 - day: 9 + year: 2021 + month: 5 + day: 19 } } diff --git a/TEST_MAPPING b/TEST_MAPPING new file mode 100644 index 0000000..e707449 --- /dev/null +++ b/TEST_MAPPING @@ -0,0 +1,11 @@ +// Generated by update_crate_tests.py for tests that depend on this crate. +{ + "presubmit": [ + { + "name": "keystore2_test" + }, + { + "name": "vpnprofilestore_test" + } + ] +} diff --git a/src/linked_hash_map.rs b/src/linked_hash_map.rs index 32733ea..191844c 100644 --- a/src/linked_hash_map.rs +++ b/src/linked_hash_map.rs @@ -441,6 +441,40 @@ where } } } + + /// If an entry with this key exists, move it to the front of the list and return a reference to + /// the value. + #[inline] + pub fn to_front(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow, + Q: Hash + Eq + ?Sized, + { + match self.raw_entry_mut().from_key(k) { + RawEntryMut::Occupied(mut occupied) => { + occupied.to_front(); + Some(occupied.into_mut()) + } + RawEntryMut::Vacant(_) => None, + } + } + + /// If an entry with this key exists, move it to the back of the list and return a reference to + /// the value. + #[inline] + pub fn to_back(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow, + Q: Hash + Eq + ?Sized, + { + match self.raw_entry_mut().from_key(k) { + RawEntryMut::Occupied(mut occupied) => { + occupied.to_back(); + Some(occupied.into_mut()) + } + RawEntryMut::Vacant(_) => None, + } + } } impl LinkedHashMap diff --git a/src/linked_hash_set.rs b/src/linked_hash_set.rs index 1ab7dbb..f55f6c5 100644 --- a/src/linked_hash_set.rs +++ b/src/linked_hash_set.rs @@ -250,7 +250,7 @@ where } #[inline] - pub fn back(&mut self) -> Option<&T> { + pub fn back(&self) -> Option<&T> { self.map.back().map(|(k, _)| k) } @@ -304,12 +304,8 @@ where S: BuildHasher, { #[inline] - fn eq(&self, other: &LinkedHashSet) -> bool { - if self.len() != other.len() { - return false; - } - - self.iter().all(|key| other.contains(key)) + fn eq(&self, other: &Self) -> bool { + self.len() == other.len() && self.iter().eq(other) } } diff --git a/src/serde.rs b/src/serde.rs index b8e307c..f44ebb3 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -31,54 +31,59 @@ where } } -#[derive(Debug)] -pub struct LinkedHashMapVisitor { - marker: PhantomData>, -} - -impl LinkedHashMapVisitor { - fn new() -> Self { - LinkedHashMapVisitor { - marker: PhantomData, - } - } -} - -impl Default for LinkedHashMapVisitor { - fn default() -> Self { - Self::new() - } -} - -impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor +impl<'de, K, V, S> Deserialize<'de> for LinkedHashMap where K: Deserialize<'de> + Eq + Hash, V: Deserialize<'de>, + S: BuildHasher + Default, { - type Value = LinkedHashMap; - - fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { - write!(formatter, "a map") - } + fn deserialize>(deserializer: D) -> Result { + #[derive(Debug)] + pub struct LinkedHashMapVisitor { + marker: PhantomData>, + } - #[inline] - fn visit_map>(self, mut map: M) -> Result { - let mut values = LinkedHashMap::with_capacity(map.size_hint().unwrap_or(0)); + impl LinkedHashMapVisitor { + fn new() -> Self { + LinkedHashMapVisitor { + marker: PhantomData, + } + } + } - while let Some((k, v)) = map.next_entry()? { - values.insert(k, v); + impl Default for LinkedHashMapVisitor { + fn default() -> Self { + Self::new() + } } - Ok(values) - } -} + impl<'de, K, V, S> Visitor<'de> for LinkedHashMapVisitor + where + K: Deserialize<'de> + Eq + Hash, + V: Deserialize<'de>, + S: BuildHasher + Default, + { + type Value = LinkedHashMap; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + write!(formatter, "a map") + } + + #[inline] + fn visit_map>(self, mut map: M) -> Result { + let mut values = LinkedHashMap::with_capacity_and_hasher( + map.size_hint().unwrap_or(0), + S::default(), + ); + + while let Some((k, v)) = map.next_entry()? { + values.insert(k, v); + } + + Ok(values) + } + } -impl<'de, K, V> Deserialize<'de> for LinkedHashMap -where - K: Deserialize<'de> + Eq + Hash, - V: Deserialize<'de>, -{ - fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_map(LinkedHashMapVisitor::default()) } } @@ -100,52 +105,57 @@ where } } -#[derive(Debug)] -pub struct LinkedHashSetVisitor { - marker: PhantomData>, -} - -impl LinkedHashSetVisitor { - fn new() -> Self { - LinkedHashSetVisitor { - marker: PhantomData, - } - } -} - -impl Default for LinkedHashSetVisitor { - fn default() -> Self { - Self::new() - } -} - -impl<'de, T> Visitor<'de> for LinkedHashSetVisitor +impl<'de, T, S> Deserialize<'de> for LinkedHashSet where T: Deserialize<'de> + Eq + Hash, + S: BuildHasher + Default, { - type Value = LinkedHashSet; - - fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { - write!(formatter, "a sequence") - } + fn deserialize>(deserializer: D) -> Result { + #[derive(Debug)] + pub struct LinkedHashSetVisitor { + marker: PhantomData>, + } - #[inline] - fn visit_seq>(self, mut seq: S) -> Result { - let mut values = LinkedHashSet::with_capacity(seq.size_hint().unwrap_or(0)); + impl LinkedHashSetVisitor { + fn new() -> Self { + LinkedHashSetVisitor { + marker: PhantomData, + } + } + } - while let Some(v) = seq.next_element()? { - values.insert(v); + impl Default for LinkedHashSetVisitor { + fn default() -> Self { + Self::new() + } } - Ok(values) - } -} + impl<'de, T, S> Visitor<'de> for LinkedHashSetVisitor + where + T: Deserialize<'de> + Eq + Hash, + S: BuildHasher + Default, + { + type Value = LinkedHashSet; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + write!(formatter, "a sequence") + } + + #[inline] + fn visit_seq>(self, mut seq: SA) -> Result { + let mut values = LinkedHashSet::with_capacity_and_hasher( + seq.size_hint().unwrap_or(0), + S::default(), + ); + + while let Some(v) = seq.next_element()? { + values.insert(v); + } + + Ok(values) + } + } -impl<'de, T> Deserialize<'de> for LinkedHashSet -where - T: Deserialize<'de> + Eq + Hash, -{ - fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_seq(LinkedHashSetVisitor::default()) } } diff --git a/tests/linked_hash_map.rs b/tests/linked_hash_map.rs index 19dcc00..fbd3d2e 100644 --- a/tests/linked_hash_map.rs +++ b/tests/linked_hash_map.rs @@ -496,3 +496,18 @@ fn test_retain() { drop(map); assert!(c.get() == 4); } + +#[test] +fn test_order_equality() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut map1: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); + let mut map2: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); + + assert_eq!(map1, map2); + + map1.to_front("4"); + assert_ne!(map1, map2); + + map2.to_front("4"); + assert_eq!(map1, map2); +} diff --git a/tests/linked_hash_set.rs b/tests/linked_hash_set.rs index 13cceae..cb75887 100644 --- a/tests/linked_hash_set.rs +++ b/tests/linked_hash_set.rs @@ -510,3 +510,18 @@ fn to_back_front_order() { set.to_front(&3); assert_eq!(set.front().copied(), Some(3)); } + +#[test] +fn test_order_equality() { + let xs = [1, 2, 3, 4, 5, 6]; + let mut set1: LinkedHashSet = xs.iter().copied().collect(); + let mut set2: LinkedHashSet = xs.iter().copied().collect(); + + assert_eq!(set1, set2); + + set1.to_front(&4); + assert_ne!(set1, set2); + + set2.to_front(&4); + assert_eq!(set1, set2); +} diff --git a/tests/serde.rs b/tests/serde.rs index fce3108..d397a24 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -1,5 +1,6 @@ #![cfg(feature = "serde_impl")] +use fxhash::FxBuildHasher; use hashlink::{LinkedHashMap, LinkedHashSet}; use serde_test::{assert_tokens, Token}; @@ -32,6 +33,35 @@ fn map_serde_tokens() { ); } +#[test] +fn map_serde_tokens_empty_generic() { + let map = LinkedHashMap::::with_hasher(FxBuildHasher::default()); + + assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); +} + +#[test] +fn map_serde_tokens_generic() { + let mut map = LinkedHashMap::with_hasher(FxBuildHasher::default()); + map.insert('a', 10); + map.insert('b', 20); + map.insert('c', 30); + + assert_tokens( + &map, + &[ + Token::Map { len: Some(3) }, + Token::Char('a'), + Token::I32(10), + Token::Char('b'), + Token::I32(20), + Token::Char('c'), + Token::I32(30), + Token::MapEnd, + ], + ); +} + #[test] fn set_serde_tokens_empty() { let set = LinkedHashSet::::new(); @@ -57,3 +87,22 @@ fn set_serde_tokens() { ], ); } + +#[test] +fn set_serde_tokens_generic() { + let mut set = LinkedHashSet::with_hasher(FxBuildHasher::default()); + set.insert('a'); + set.insert('b'); + set.insert('c'); + + assert_tokens( + &set, + &[ + Token::Seq { len: Some(3) }, + Token::Char('a'), + Token::Char('b'), + Token::Char('c'), + Token::SeqEnd, + ], + ); +} -- cgit v1.2.3 From ac8ff581d6f15c59d0f4aaf672503b3bb2e8d815 Mon Sep 17 00:00:00 2001 From: easoncylee Date: Fri, 2 Jul 2021 11:27:33 +0800 Subject: Update vpnprofilestore_test to legacykeystore_test in TEST_MAPPING The test had been changed to legacykeystore_test from ag/14968529 Bug: 192796637 Test: presubmit Change-Id: I8d5307e9f08a908334070faab40093137b8b83d3 --- TEST_MAPPING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index e707449..48ee89d 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -5,7 +5,7 @@ "name": "keystore2_test" }, { - "name": "vpnprofilestore_test" + "name": "legacykeystore_test" } ] } -- cgit v1.2.3 From 86898edaca2ebd5a8a93b827ef961e6077781890 Mon Sep 17 00:00:00 2001 From: Joel Galenson Date: Mon, 29 Nov 2021 14:03:57 -0800 Subject: Refresh Android.bp, cargo2android.json, TEST_MAPPING. Test: None Change-Id: I24d99bdb22e05344ead547d19d3a851ad66ba608 --- Android.bp | 13 +++---------- TEST_MAPPING | 8 ++++++++ cargo2android.json | 4 ++++ 3 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 cargo2android.json diff --git a/Android.bp b/Android.bp index 1a194ac..260ac53 100644 --- a/Android.bp +++ b/Android.bp @@ -1,4 +1,4 @@ -// This file is generated by cargo2android.py --device --run --dependencies. +// This file is generated by cargo2android.py --config cargo2android.json. // Do not modify this file as changes will be overridden on upgrade. package { @@ -41,18 +41,11 @@ rust_library { name: "libhashlink", host_supported: true, crate_name: "hashlink", + cargo_env_compat: true, + cargo_pkg_version: "0.7.0", srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ "libhashbrown", ], } - -// dependent_library ["feature_list"] -// ahash-0.7.2 "folded_multiply,runtime-rng,specialize" -// cfg-if-1.0.0 -// getrandom-0.2.2 -// hashbrown-0.11.2 "ahash,default,inline-more" -// libc-0.2.94 -// once_cell-1.7.2 "alloc,race,unstable" -// version_check-0.9.3 diff --git a/TEST_MAPPING b/TEST_MAPPING index 48ee89d..91f37bf 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -7,5 +7,13 @@ { "name": "legacykeystore_test" } + ], + "presubmit-rust": [ + { + "name": "keystore2_test" + }, + { + "name": "legacykeystore_test" + } ] } diff --git a/cargo2android.json b/cargo2android.json new file mode 100644 index 0000000..bf78496 --- /dev/null +++ b/cargo2android.json @@ -0,0 +1,4 @@ +{ + "device": true, + "run": true +} \ No newline at end of file -- cgit v1.2.3