diff --git a/Cargo.toml b/Cargo.toml index bff2115..b1c2e64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hashlink" -version = "0.9.1" +version = "0.10.0" authors = ["kyren "] edition = "2018" description = "HashMap-like containers that hold their key-value pairs in a user controllable order" @@ -9,6 +9,7 @@ documentation = "https://docs.rs/hashlink" readme = "README.md" keywords = ["data-structures", "no_std"] license = "MIT OR Apache-2.0" +rust-version = "1.65" [badges] circle-ci = { repository = "kyren/hashlink", branch = "master" } @@ -17,9 +18,10 @@ circle-ci = { repository = "kyren/hashlink", branch = "master" } serde_impl = ["serde"] [dependencies] -hashbrown = { version = "0.14.3", default-features = false, features = ["ahash", "inline-more"] } +foldhash = { version = "0.1.3", default-features = false } +hashbrown = { version = "0.15", default-features = false, features = ["default-hasher", "inline-more"] } serde = { version = "1.0", default-features = false, optional = true } [dev-dependencies] serde_test = "1.0" -rustc-hash = "1.1" +rustc-hash = "2" diff --git a/src/lib.rs b/src/lib.rs index 4d80905..381a926 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,101 @@ pub mod lru_cache; #[cfg(feature = "serde_impl")] pub mod serde; +use core::hash::{BuildHasher, Hasher}; + pub use linked_hash_map::LinkedHashMap; pub use linked_hash_set::LinkedHashSet; pub use lru_cache::LruCache; + +/// Default hash builder, matches hashbrown's default hasher. +/// +/// See [`DefaultHasher`] for more details. +#[derive(Clone, Copy, Default, Debug)] +pub struct DefaultHashBuilder(hashbrown::DefaultHashBuilder); + +impl BuildHasher for DefaultHashBuilder { + type Hasher = DefaultHasher; + + #[inline] + fn build_hasher(&self) -> Self::Hasher { + DefaultHasher(self.0.build_hasher()) + } +} + +/// Default hasher, as selected by hashbrown. +/// +/// Currently this is [`foldhash::fast::FoldHasher`]. +#[derive(Clone)] +pub struct DefaultHasher(foldhash::fast::FoldHasher); + +impl Hasher for DefaultHasher { + #[inline] + fn write(&mut self, bytes: &[u8]) { + self.0.write(bytes) + } + + #[inline] + fn write_u8(&mut self, i: u8) { + self.0.write_u8(i) + } + + #[inline] + fn write_u16(&mut self, i: u16) { + self.0.write_u16(i) + } + + #[inline] + fn write_u32(&mut self, i: u32) { + self.0.write_u32(i) + } + + #[inline] + fn write_u64(&mut self, i: u64) { + self.0.write_u64(i) + } + + #[inline] + fn write_u128(&mut self, i: u128) { + self.0.write_u128(i) + } + + #[inline] + fn write_usize(&mut self, i: usize) { + self.0.write_usize(i) + } + + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } + + #[inline] + fn write_i8(&mut self, i: i8) { + self.0.write_i8(i) + } + + #[inline] + fn write_i16(&mut self, i: i16) { + self.0.write_i16(i) + } + + #[inline] + fn write_i32(&mut self, i: i32) { + self.0.write_i32(i) + } + + #[inline] + fn write_i64(&mut self, i: i64) { + self.0.write_i64(i) + } + + #[inline] + fn write_i128(&mut self, i: i128) { + self.0.write_i128(i) + } + + #[inline] + fn write_isize(&mut self, i: isize) { + self.0.write_isize(i) + } +} diff --git a/src/linked_hash_map.rs b/src/linked_hash_map.rs index f4274f3..1f72aae 100644 --- a/src/linked_hash_map.rs +++ b/src/linked_hash_map.rs @@ -12,9 +12,10 @@ use core::{ }; use alloc::boxed::Box; -use hashbrown::hash_map::DefaultHashBuilder; use hashbrown::hash_table::{self, HashTable}; +use crate::DefaultHashBuilder; + pub enum TryReserveError { CapacityOverflow, AllocError { layout: Layout }, @@ -972,7 +973,7 @@ where } } -unsafe impl<'a, K, V, S> Send for RawEntryBuilder<'a, K, V, S> +unsafe impl Send for RawEntryBuilder<'_, K, V, S> where K: Send, V: Send, @@ -980,7 +981,7 @@ where { } -unsafe impl<'a, K, V, S> Sync for RawEntryBuilder<'a, K, V, S> +unsafe impl Sync for RawEntryBuilder<'_, K, V, S> where K: Sync, V: Sync, @@ -1043,7 +1044,7 @@ where } } -unsafe impl<'a, K, V, S> Send for RawEntryBuilderMut<'a, K, V, S> +unsafe impl Send for RawEntryBuilderMut<'_, K, V, S> where K: Send, V: Send, @@ -1051,7 +1052,7 @@ where { } -unsafe impl<'a, K, V, S> Sync for RawEntryBuilderMut<'a, K, V, S> +unsafe impl Sync for RawEntryBuilderMut<'_, K, V, S> where K: Sync, V: Sync, @@ -1346,7 +1347,7 @@ impl fmt::Debug for RawEntryBuilder<'_, K, V, S> { } } -unsafe impl<'a, K, V, S> Send for RawOccupiedEntryMut<'a, K, V, S> +unsafe impl Send for RawOccupiedEntryMut<'_, K, V, S> where K: Send, V: Send, @@ -1354,7 +1355,7 @@ where { } -unsafe impl<'a, K, V, S> Sync for RawOccupiedEntryMut<'a, K, V, S> +unsafe impl Sync for RawOccupiedEntryMut<'_, K, V, S> where K: Sync, V: Sync, @@ -1362,7 +1363,7 @@ where { } -unsafe impl<'a, K, V, S> Send for RawVacantEntryMut<'a, K, V, S> +unsafe impl Send for RawVacantEntryMut<'_, K, V, S> where K: Send, V: Send, @@ -1370,7 +1371,7 @@ where { } -unsafe impl<'a, K, V, S> Sync for RawVacantEntryMut<'a, K, V, S> +unsafe impl Sync for RawVacantEntryMut<'_, K, V, S> where K: Sync, V: Sync, @@ -1444,14 +1445,14 @@ impl Drain<'_, K, V> { } } -unsafe impl<'a, K, V> Send for Iter<'a, K, V> +unsafe impl Send for Iter<'_, K, V> where K: Send, V: Send, { } -unsafe impl<'a, K, V> Send for IterMut<'a, K, V> +unsafe impl Send for IterMut<'_, K, V> where K: Send, V: Send, @@ -1465,21 +1466,21 @@ where { } -unsafe impl<'a, K, V> Send for Drain<'a, K, V> +unsafe impl Send for Drain<'_, K, V> where K: Send, V: Send, { } -unsafe impl<'a, K, V> Sync for Iter<'a, K, V> +unsafe impl Sync for Iter<'_, K, V> where K: Sync, V: Sync, { } -unsafe impl<'a, K, V> Sync for IterMut<'a, K, V> +unsafe impl Sync for IterMut<'_, K, V> where K: Sync, V: Sync, @@ -1493,14 +1494,14 @@ where { } -unsafe impl<'a, K, V> Sync for Drain<'a, K, V> +unsafe impl Sync for Drain<'_, K, V> where K: Sync, V: Sync, { } -impl<'a, K, V> Clone for Iter<'a, K, V> { +impl Clone for Iter<'_, K, V> { #[inline] fn clone(&self) -> Self { Iter { ..*self } @@ -1617,7 +1618,7 @@ impl Iterator for IntoIter { } } -impl<'a, K, V> Iterator for Drain<'a, K, V> { +impl Iterator for Drain<'_, K, V> { type Item = (K, V); #[inline] @@ -1690,7 +1691,7 @@ impl DoubleEndedIterator for IntoIter { } } -impl<'a, K, V> DoubleEndedIterator for Drain<'a, K, V> { +impl DoubleEndedIterator for Drain<'_, K, V> { #[inline] fn next_back(&mut self) -> Option<(K, V)> { if self.remaining == 0 { @@ -1707,9 +1708,9 @@ impl<'a, K, V> DoubleEndedIterator for Drain<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {} +impl ExactSizeIterator for Iter<'_, K, V> {} -impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {} +impl ExactSizeIterator for IterMut<'_, K, V> {} impl ExactSizeIterator for IntoIter {} @@ -1727,7 +1728,7 @@ impl Drop for IntoIter { } } -impl<'a, K, V> Drop for Drain<'a, K, V> { +impl Drop for Drain<'_, K, V> { #[inline] fn drop(&mut self) { for _ in 0..self.remaining { @@ -1762,7 +1763,7 @@ pub struct CursorMut<'a, K, V, S> { table: &'a mut hashbrown::HashTable>>, } -impl<'a, K, V, S> CursorMut<'a, K, V, S> { +impl CursorMut<'_, K, V, S> { /// Returns an `Option` of the current element in the list, provided it is not the /// _guard_ node, and `None` overwise. #[inline] @@ -1944,7 +1945,7 @@ impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { +impl ExactSizeIterator for Keys<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() @@ -1992,7 +1993,7 @@ impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { +impl ExactSizeIterator for Values<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() @@ -2035,7 +2036,7 @@ impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { } } -impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { +impl ExactSizeIterator for ValuesMut<'_, K, V> { #[inline] fn len(&self) -> usize { self.inner.len() @@ -2163,6 +2164,7 @@ impl Node { } trait OptNonNullExt { + #[allow(clippy::wrong_self_convention)] fn as_ptr(self) -> *mut T; } @@ -2321,7 +2323,7 @@ struct DropFilteredValues<'a, K, V> { cur_free: Option>>, } -impl<'a, K, V> DropFilteredValues<'a, K, V> { +impl DropFilteredValues<'_, K, V> { #[inline] fn drop_later(&mut self, node: NonNull>) { unsafe { @@ -2331,7 +2333,7 @@ impl<'a, K, V> DropFilteredValues<'a, K, V> { } } -impl<'a, K, V> Drop for DropFilteredValues<'a, K, V> { +impl Drop for DropFilteredValues<'_, K, V> { fn drop(&mut self) { unsafe { let end_free = self.cur_free; diff --git a/src/linked_hash_set.rs b/src/linked_hash_set.rs index b3361fb..ecaf9ea 100644 --- a/src/linked_hash_set.rs +++ b/src/linked_hash_set.rs @@ -6,9 +6,8 @@ use core::{ ops::{BitAnd, BitOr, BitXor, Sub}, }; -use hashbrown::hash_map::DefaultHashBuilder; - use crate::linked_hash_map::{self, LinkedHashMap, TryReserveError}; +use crate::DefaultHashBuilder; pub struct LinkedHashSet { map: LinkedHashMap, @@ -147,19 +146,19 @@ where } #[inline] - pub fn contains(&self, value: &Q) -> bool + pub fn contains(&self, value: &Q) -> bool where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, { self.map.contains_key(value) } #[inline] - pub fn get(&self, value: &Q) -> Option<&T> + pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, { self.map.raw_entry().from_key(value).map(|p| p.0) } @@ -174,10 +173,10 @@ where } #[inline] - pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T + pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, F: FnOnce(&Q) -> T, { self.map @@ -228,19 +227,19 @@ where } #[inline] - pub fn remove(&mut self, value: &Q) -> bool + pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, { self.map.remove(value).is_some() } #[inline] - pub fn take(&mut self, value: &Q) -> Option + pub fn take(&mut self, value: &Q) -> Option where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, { match self.map.raw_entry_mut().from_key(value) { linked_hash_map::RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry().0), @@ -269,10 +268,10 @@ where } #[inline] - pub fn to_front(&mut self, value: &Q) -> bool + pub fn to_front(&mut self, value: &Q) -> bool where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, { match self.map.raw_entry_mut().from_key(value) { linked_hash_map::RawEntryMut::Occupied(mut occupied) => { @@ -284,10 +283,10 @@ where } #[inline] - pub fn to_back(&mut self, value: &Q) -> bool + pub fn to_back(&mut self, value: &Q) -> bool where T: Borrow, - Q: Hash + Eq, + Q: Hash + Eq + ?Sized, { match self.map.raw_entry_mut().from_key(value) { linked_hash_map::RawEntryMut::Occupied(mut occupied) => { @@ -403,7 +402,7 @@ where } } -impl<'a, 'b, T, S> BitOr<&'b LinkedHashSet> for &'a LinkedHashSet +impl BitOr<&LinkedHashSet> for &LinkedHashSet where T: Eq + Hash + Clone, S: BuildHasher + Default, @@ -416,7 +415,7 @@ where } } -impl<'a, 'b, T, S> BitAnd<&'b LinkedHashSet> for &'a LinkedHashSet +impl BitAnd<&LinkedHashSet> for &LinkedHashSet where T: Eq + Hash + Clone, S: BuildHasher + Default, @@ -429,7 +428,7 @@ where } } -impl<'a, 'b, T, S> BitXor<&'b LinkedHashSet> for &'a LinkedHashSet +impl BitXor<&LinkedHashSet> for &LinkedHashSet where T: Eq + Hash + Clone, S: BuildHasher + Default, @@ -442,7 +441,7 @@ where } } -impl<'a, 'b, T, S> Sub<&'b LinkedHashSet> for &'a LinkedHashSet +impl Sub<&LinkedHashSet> for &LinkedHashSet where T: Eq + Hash + Clone, S: BuildHasher + Default, @@ -529,7 +528,7 @@ impl<'a, K> Iterator for Iter<'a, K> { } } -impl<'a, K> ExactSizeIterator for Iter<'a, K> {} +impl ExactSizeIterator for Iter<'_, K> {} impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[inline] @@ -538,7 +537,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { } } -impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> { +impl fmt::Debug for Iter<'_, K> { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() @@ -568,7 +567,7 @@ impl DoubleEndedIterator for IntoIter { } } -impl<'a, K> Iterator for Drain<'a, K> { +impl Iterator for Drain<'_, K> { type Item = K; #[inline] @@ -582,14 +581,14 @@ impl<'a, K> Iterator for Drain<'a, K> { } } -impl<'a, K> DoubleEndedIterator for Drain<'a, K> { +impl DoubleEndedIterator for Drain<'_, K> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back().map(|(k, _)| k) } } -impl<'a, K> ExactSizeIterator for Drain<'a, K> {} +impl ExactSizeIterator for Drain<'_, K> {} impl<'a, T, S> Clone for Intersection<'a, T, S> { #[inline] @@ -629,7 +628,7 @@ where } } -impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> +impl fmt::Debug for Intersection<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -678,7 +677,7 @@ where } } -impl<'a, T, S> fmt::Debug for Difference<'a, T, S> +impl fmt::Debug for Difference<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -716,7 +715,7 @@ where } } -impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S> +impl fmt::Debug for SymmetricDifference<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, @@ -736,7 +735,7 @@ impl<'a, T, S> Clone for Union<'a, T, S> { } } -impl<'a, T, S> fmt::Debug for Union<'a, T, S> +impl fmt::Debug for Union<'_, T, S> where T: fmt::Debug + Eq + Hash, S: BuildHasher, diff --git a/src/lru_cache.rs b/src/lru_cache.rs index 1db27ce..daf9bf9 100644 --- a/src/lru_cache.rs +++ b/src/lru_cache.rs @@ -2,19 +2,17 @@ use core::{ borrow::Borrow, fmt, hash::{BuildHasher, Hash}, - usize, }; -use hashbrown::hash_map; - use crate::linked_hash_map::{self, LinkedHashMap}; +use crate::DefaultHashBuilder; pub use crate::linked_hash_map::{ Drain, Entry, IntoIter, Iter, IterMut, OccupiedEntry, RawEntryBuilder, RawEntryBuilderMut, RawOccupiedEntryMut, RawVacantEntryMut, VacantEntry, }; -pub struct LruCache { +pub struct LruCache { map: LinkedHashMap, max_size: usize, } diff --git a/tests/linked_hash_map.rs b/tests/linked_hash_map.rs index 1ada735..5317595 100644 --- a/tests/linked_hash_map.rs +++ b/tests/linked_hash_map.rs @@ -354,7 +354,7 @@ fn test_consuming_iter_with_free_list() { fn test_into_iter_drop() { struct Counter<'a>(&'a mut usize); - impl<'a> Drop for Counter<'a> { + impl Drop for Counter<'_> { fn drop(&mut self) { *self.0 += 1; } @@ -386,7 +386,7 @@ fn test_drain() { struct Counter(Rc>); - impl<'a> Drop for Counter { + impl Drop for Counter { fn drop(&mut self) { self.0.set(self.0.get() + 1); } @@ -476,7 +476,7 @@ fn test_retain() { struct Counter(Rc>); - impl<'a> Drop for Counter { + impl Drop for Counter { fn drop(&mut self) { self.0.set(self.0.get() + 1); } diff --git a/tests/linked_hash_set.rs b/tests/linked_hash_set.rs index 477f135..e910ab3 100644 --- a/tests/linked_hash_set.rs +++ b/tests/linked_hash_set.rs @@ -1,5 +1,5 @@ -use hashbrown::hash_map::DefaultHashBuilder; use hashlink::linked_hash_set::{self, LinkedHashSet}; +use hashlink::DefaultHashBuilder; #[allow(dead_code)] fn assert_covariance() { @@ -344,9 +344,7 @@ fn test_drain() { assert_eq!(last_i, 49); } - for _ in &s { - panic!("s should be empty!"); - } + assert_eq!((&s).into_iter().count(), 0); s.extend(1..100); } @@ -493,7 +491,6 @@ fn double_ended_iter() { assert_eq!(iter.next_back(), None); assert_eq!(iter.next(), None); assert_eq!(iter.next_back(), None); - drop(iter); let mut iter = set.drain(); assert_eq!(iter.next(), Some(1)); diff --git a/tests/lru_cache.rs b/tests/lru_cache.rs index f863c70..5ac1b56 100644 --- a/tests/lru_cache.rs +++ b/tests/lru_cache.rs @@ -23,7 +23,7 @@ fn test_put_update() { fn test_contains_key() { let mut cache = LruCache::new(1); cache.insert("1", 10); - assert_eq!(cache.contains_key("1"), true); + assert!(cache.contains_key("1")); } #[test]