From 592319711b31aa483a41ebe47f9b458694253cdf Mon Sep 17 00:00:00 2001 From: "Jesse A. Tov" Date: Wed, 1 Dec 2021 13:35:58 -0600 Subject: [PATCH] Documented time complexities of all operations. --- README.md | 12 ++-- src/lib.rs | 21 +++++-- src/ptr_weak_hash_set.rs | 48 ++++++++++++++++ src/ptr_weak_key_hash_map.rs | 73 +++++++++++++++++++++++ src/ptr_weak_weak_hash_map.rs | 64 +++++++++++++++++++++ src/weak_hash_set.rs | 50 ++++++++++++++++ src/weak_key_hash_map.rs | 105 ++++++++++++++++++++++++++++++++++ src/weak_value_hash_map.rs | 88 ++++++++++++++++++++++++++++ src/weak_weak_hash_map.rs | 94 ++++++++++++++++++++++++++++++ 9 files changed, 545 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b6cf3b0..9d4ac80 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,19 @@ This crate defines several kinds of weak hash maps and sets. See the [full API documentation](http://docs.rs/weak-table/) for details. -This crate supports Rust version 1.46 and later. - -### Crate Features +### Rust version support -`weak-table` is built with one feature by default: +This crate supports Rust version 1.46 and later. - - `std`: enables functionality dependent on the `std` lib +### Crate features +`weak-table` is built with the `std` feature, which enables +functionality dependent on the `std` library, enabled by default. Optionally, the following dependency may be enabled: - `ahash`: use `ahash`’s hasher rather than the `std` hasher -If the `std` feature is disabled (for no_std) then the `ahash` dependency must be enabled. +If the `std` feature is disabled (for no_std) then the `ahash` dependency **must** be enabled. ### Examples diff --git a/src/lib.rs b/src/lib.rs index b0aa034..b1cde61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,19 +26,32 @@ //! To add support for your own weak pointers, see //! [the traits `WeakElement` and `WeakKey`](traits/). //! +//! ## Rust version support +//! //! This crate supports Rust version 1.46 and later. //! -//! # Crate Features +//! ## Asymptotic complexity +//! +//! Most operations have documented asymptotic time complexities. When time complexities are +//! given in big-*O* notation, the following parameters are used consistently: +//! +//! - *n*: the *capacity* of the map or set being accessed or constructed +//! +//! - *m*: the *capacity* of a second map/set involved in a submap/subset operation +//! +//! - *p*: the length of the probe sequence for the key in question //! -//! `weak-table` is built with one feature by default: +//! Note that *p* ∈ *O*(*n*), but we expect it to be *O*(1). //! -//! - `std`: enables functionality dependent on the `std` lib +//! # Crate features //! +//! `weak-table` is built with the `std` feature, which enables +//! functionality dependent on the `std` library, enabled by default. //! Optionally, the following dependency may be enabled: //! //! - `ahash`: use `ahash`’s hasher rather than the `std` hasher //! -//! If the `std` feature is disabled (for no_std) then the `ahash` dependency must be enabled. +//! If the `std` feature is disabled (for no_std) then the `ahash` dependency **must** be enabled. //! //! # Examples //! diff --git a/src/ptr_weak_hash_set.rs b/src/ptr_weak_hash_set.rs index d2fc871..9f6cb71 100644 --- a/src/ptr_weak_hash_set.rs +++ b/src/ptr_weak_hash_set.rs @@ -12,11 +12,15 @@ impl PtrWeakHashSet where T::Strong: Deref { /// Creates an empty `PtrWeakHashSet`. + /// + /// *O*(1) time pub fn new() -> Self { PtrWeakHashSet(base::PtrWeakKeyHashMap::new()) } /// Creates an empty `PtrWeakHashSet` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { PtrWeakHashSet(base::PtrWeakKeyHashMap::with_capacity(capacity)) } @@ -26,41 +30,57 @@ impl PtrWeakHashSet where T::Strong: Deref { /// Creates an empty `PtrWeakHashSet` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { PtrWeakHashSet(base::PtrWeakKeyHashMap::with_hasher(hash_builder)) } /// Creates an empty `PtrWeakHashSet` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { PtrWeakHashSet(base::PtrWeakKeyHashMap::with_capacity_and_hasher(capacity, hash_builder)) } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { self.0.hasher() } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.0.capacity() } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.0.remove_expired() } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { self.0.reserve(additional_capacity) } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.0.shrink_to_fit() } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.0.len() } @@ -69,6 +89,8 @@ impl PtrWeakHashSet /// /// This could answer `false` for an empty set whose elements have /// expired but have yet to be collected. + /// + /// *O*(1) time pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -77,27 +99,37 @@ impl PtrWeakHashSet /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired elements. + /// + /// *O*(1) time pub fn load_factor(&self) -> f32 { self.0.load_factor() } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.0.clear() } /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains(&self, key: &T::Strong) -> bool { self.0.contains_key(key) } /// Unconditionally inserts the value, returning the old value if already present. Does not /// replace the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: T::Strong) -> bool { self.0.insert(key, ()).is_some() } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &T::Strong) -> bool { self.0.remove(key).is_some() } @@ -105,6 +137,8 @@ impl PtrWeakHashSet /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. + /// + /// *O*(*n*) time pub fn retain(&mut self, mut f: F) where F: FnMut(T::Strong) -> bool { @@ -112,6 +146,10 @@ impl PtrWeakHashSet } /// Is self a subset of other? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_subset(&self, other: &PtrWeakHashSet) -> bool where S1: BuildHasher { @@ -168,11 +206,15 @@ impl PtrWeakHashSet where T::Strong: Deref { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter { Iter(self.0.keys()) } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain { Drain(self.0.drain()) } @@ -235,6 +277,9 @@ impl IntoIterator for PtrWeakHashSet { type Item = T::Strong; type IntoIter = IntoIter; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter()) } @@ -246,6 +291,9 @@ impl<'a, T: WeakElement, S> IntoIterator for &'a PtrWeakHashSet type Item = T::Strong; type IntoIter = Iter<'a, T>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { Iter(self.0.keys()) } diff --git a/src/ptr_weak_key_hash_map.rs b/src/ptr_weak_key_hash_map.rs index 686ef60..2cd5591 100644 --- a/src/ptr_weak_key_hash_map.rs +++ b/src/ptr_weak_key_hash_map.rs @@ -13,11 +13,15 @@ impl PtrWeakKeyHashMap where K::Strong: Deref { /// Creates an empty `PtrWeakKeyHashMap`. + /// + /// *O*(1) time pub fn new() -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::new()) } /// Creates an empty `PtrWeakKeyHashMap` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::with_capacity(capacity)) } @@ -27,41 +31,57 @@ impl PtrWeakKeyHashMap where K::Strong: Deref { /// Creates an empty `PtrWeakKeyHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::with_hasher(hash_builder)) } /// Creates an empty `PtrWeakKeyHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::with_capacity_and_hasher(capacity, hash_builder)) } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { self.0.hasher() } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.0.capacity() } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.0.remove_expired() } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { self.0.reserve(additional_capacity) } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.0.shrink_to_fit() } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.0.len() } @@ -70,6 +90,8 @@ impl PtrWeakKeyHashMap /// /// This could answer `false` for an empty map whose keys have /// expired but have yet to be collected. + /// + /// *O*(1) time pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -77,42 +99,58 @@ impl PtrWeakKeyHashMap /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired keys. + /// + /// *O*(1) time pub fn load_factor(&self) -> f32 { self.0.load_factor() } /// Gets the requested entry. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn entry(&mut self, key: K::Strong) -> Entry, V> { self.0.entry(key) } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.0.clear() } /// Returns a reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &K::Strong) -> Option<&V> { self.0.get(&(key.deref() as *const _)) } /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains_key(&self, key:&K::Strong) -> bool { self.0.contains_key(&(key.deref() as *const _)) } /// Returns a mutable reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_mut(&mut self, key: &K::Strong) -> Option<&mut V> { self.0.get_mut(&(key.deref() as *const _)) } /// Unconditionally inserts the value, returning the old value if already present. Does not /// replace the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: K::Strong, value: V) -> Option { self.0.insert(key, value) } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &K::Strong) -> Option { self.0.remove(&(key.deref() as *const _)) } @@ -120,6 +158,8 @@ impl PtrWeakKeyHashMap /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. + /// + /// *O*(*n*) time pub fn retain(&mut self, f: F) where F: FnMut(K::Strong, &mut V) -> bool { @@ -130,6 +170,10 @@ impl PtrWeakKeyHashMap /// /// In particular, all the keys of self must be in other and the values must compare true with /// value_equal. + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn submap_with(&self, other: &PtrWeakKeyHashMap, value_equal: F) -> bool where F: FnMut(&V, &V1) -> bool, S1: BuildHasher @@ -138,6 +182,10 @@ impl PtrWeakKeyHashMap } /// Is self a submap of other? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap(&self, other: &PtrWeakKeyHashMap) -> bool where V: PartialEq, S1: BuildHasher @@ -146,6 +194,10 @@ impl PtrWeakKeyHashMap } /// Are the keys of self a subset of the keys of other? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn domain_is_subset(&self, other: &PtrWeakKeyHashMap) -> bool where S1: BuildHasher { @@ -157,31 +209,43 @@ impl PtrWeakKeyHashMap where K::Strong: Deref { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter, V> { self.0.iter() } /// Gets an iterator over the keys. + /// + /// *O*(1) time pub fn keys(&self) -> Keys, V> { self.0.keys() } /// Gets an iterator over the values. + /// + /// *O*(1) time pub fn values(&self) -> Values, V> { self.0.values() } /// Gets an iterator over the keys and mutable values. + /// + /// *O*(1) time pub fn iter_mut(&mut self) -> IterMut, V> { self.0.iter_mut() } /// Gets an iterator over the mutable values. + /// + /// *O*(1) time pub fn values_mut(&mut self) -> ValuesMut, V> { self.0.values_mut() } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain, V> { self.0.drain() } @@ -279,6 +343,9 @@ impl IntoIterator for PtrWeakKeyHashMap { type Item = (K::Strong, V); type IntoIter = IntoIter, V>; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } @@ -288,6 +355,9 @@ impl<'a, K: WeakElement, V, S> IntoIterator for &'a PtrWeakKeyHashMap { type Item = (K::Strong, &'a V); type IntoIter = Iter<'a, ByPtr, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { (&self.0).into_iter() } @@ -297,6 +367,9 @@ impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut PtrWeakKeyHashMap, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { (&mut self.0).into_iter() } diff --git a/src/ptr_weak_weak_hash_map.rs b/src/ptr_weak_weak_hash_map.rs index 1f75834..fb49ae7 100644 --- a/src/ptr_weak_weak_hash_map.rs +++ b/src/ptr_weak_weak_hash_map.rs @@ -14,11 +14,15 @@ impl PtrWeakWeakHashMap where K::Strong: Deref { /// Creates an empty `PtrWeakWeakHashMap`. + /// + /// *O*(1) time pub fn new() -> Self { PtrWeakWeakHashMap(base::WeakWeakHashMap::new()) } /// Creates an empty `PtrWeakWeakHashMap` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { PtrWeakWeakHashMap(base::WeakWeakHashMap::with_capacity(capacity)) } @@ -28,41 +32,57 @@ impl PtrWeakWeakHashMap Self { PtrWeakWeakHashMap(base::WeakWeakHashMap::with_hasher(hash_builder)) } /// Creates an empty `PtrWeakWeakHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { PtrWeakWeakHashMap(base::WeakWeakHashMap::with_capacity_and_hasher(capacity, hash_builder)) } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { self.0.hasher() } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.0.capacity() } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.0.remove_expired() } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { self.0.reserve(additional_capacity) } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.0.shrink_to_fit() } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.0.len() } @@ -71,6 +91,8 @@ impl PtrWeakWeakHashMap bool { self.0.is_empty() } @@ -78,37 +100,51 @@ impl PtrWeakWeakHashMap f32 { self.0.load_factor() } /// Gets the requested entry. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn entry(&mut self, key: K::Strong) -> Entry, V> { self.0.entry(key) } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.0.clear() } /// Returns a reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &K::Strong) -> Option { self.0.get(&(key.deref() as *const _)) } /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains_key(&self, key: &K::Strong) -> bool { self.0.contains_key(&(key.deref() as *const _)) } /// Unconditionally inserts the value, returning the old value if already present. Does not /// replace the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: K::Strong, value: V::Strong) -> Option { self.0.insert(key, value) } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &K::Strong) -> Option { self.0.remove(&(key.deref() as *const _)) } @@ -116,6 +152,8 @@ impl PtrWeakWeakHashMap(&mut self, f: F) where F: FnMut(K::Strong, V::Strong) -> bool { @@ -126,6 +164,10 @@ impl PtrWeakWeakHashMap(&self, other: &PtrWeakWeakHashMap, value_equal: F) -> bool where F: FnMut(V::Strong, V1::Strong) -> bool, V1: WeakElement, @@ -135,6 +177,10 @@ impl PtrWeakWeakHashMap(&self, other: &PtrWeakWeakHashMap) -> bool where V1: WeakElement, V::Strong: PartialEq, @@ -144,6 +190,10 @@ impl PtrWeakWeakHashMap(&self, other: &PtrWeakWeakHashMap) -> bool where V1: WeakElement, S1: BuildHasher @@ -156,21 +206,29 @@ impl PtrWeakWeakHashMap where K::Strong: Deref { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter, V> { self.0.iter() } /// Gets an iterator over the keys. + /// + /// *O*(1) time pub fn keys(&self) -> Keys, V> { self.0.keys() } /// Gets an iterator over the values. + /// + /// *O*(1) time pub fn values(&self) -> Values, V> { self.0.values() } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain, V> { self.0.drain() } @@ -241,6 +299,9 @@ impl IntoIterator for PtrWeakWeakHashMap, V>; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } @@ -250,6 +311,9 @@ impl<'a, K: WeakElement, V: WeakElement, S> IntoIterator for &'a PtrWeakWeakHash type Item = (K::Strong, V::Strong); type IntoIter = Iter<'a, ByPtr, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { (&self.0).into_iter() } diff --git a/src/weak_hash_set.rs b/src/weak_hash_set.rs index fc3a117..bbff3b8 100644 --- a/src/weak_hash_set.rs +++ b/src/weak_hash_set.rs @@ -9,11 +9,15 @@ pub use super::WeakHashSet; impl WeakHashSet { /// Creates an empty `WeakHashSet`. + /// + /// *O*(1) time pub fn new() -> Self { WeakHashSet(base::WeakKeyHashMap::new()) } /// Creates an empty `WeakHashSet` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { WeakHashSet(base::WeakKeyHashMap::with_capacity(capacity)) } @@ -21,41 +25,57 @@ impl WeakHashSet { impl WeakHashSet { /// Creates an empty `WeakHashSet` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { WeakHashSet(base::WeakKeyHashMap::with_hasher(hash_builder)) } /// Creates an empty `WeakHashSet` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { WeakHashSet(base::WeakKeyHashMap::with_capacity_and_hasher(capacity, hash_builder)) } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { self.0.hasher() } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.0.capacity() } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.0.remove_expired() } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { self.0.reserve(additional_capacity) } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.0.shrink_to_fit() } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.0.len() } @@ -64,6 +84,8 @@ impl WeakHashSet { /// /// Note that this may return false even if all keys in the set have /// expired, if they haven't been collected yet. + /// + /// *O*(1) time pub fn is_empty(&self) -> bool { self.0.is_empty() } @@ -71,11 +93,15 @@ impl WeakHashSet { /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired elements. + /// + /// *O*(1) time pub fn load_factor(&self) -> f32 { self.0.load_factor() } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.0.clear() } @@ -83,6 +109,8 @@ impl WeakHashSet { // Non-ptr WeakHashSet should probably have `get` method. /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains(&self, key: &Q) -> bool where Q: ?Sized + Eq + Hash, T::Key: Borrow @@ -108,6 +136,8 @@ impl WeakHashSet { /// /// assert!(Rc::ptr_eq( &a, &also_a )); /// ``` + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &Q) -> Option where Q: ?Sized + Eq + Hash, T::Key: Borrow @@ -117,11 +147,15 @@ impl WeakHashSet { /// Unconditionally inserts the value, returning the old value if already present. Does not /// replace the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: T::Strong) -> bool { self.0.insert(key, ()).is_some() } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &Q) -> bool where Q: ?Sized + Eq + Hash, T::Key: Borrow @@ -132,6 +166,8 @@ impl WeakHashSet { /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. + /// + /// *O*(*n*) time pub fn retain(&mut self, mut f: F) where F: FnMut(T::Strong) -> bool { @@ -139,6 +175,10 @@ impl WeakHashSet { } /// Is self a subset of other? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_subset(&self, other: &WeakHashSet) -> bool where S1: BuildHasher { @@ -193,11 +233,15 @@ impl<'a, T: WeakElement> Iterator for Drain<'a, T> { impl WeakHashSet { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter { Iter(self.0.keys()) } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain { Drain(self.0.drain()) } @@ -251,6 +295,9 @@ impl IntoIterator for WeakHashSet { type Item = T::Strong; type IntoIter = IntoIter; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { IntoIter(self.0.into_iter()) } @@ -260,6 +307,9 @@ impl<'a, T: WeakKey, S> IntoIterator for &'a WeakHashSet { type Item = T::Strong; type IntoIter = Iter<'a, T>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { Iter(self.0.keys()) } diff --git a/src/weak_key_hash_map.rs b/src/weak_key_hash_map.rs index c08f0f9..7dcb8c4 100644 --- a/src/weak_key_hash_map.rs +++ b/src/weak_key_hash_map.rs @@ -194,11 +194,15 @@ impl Iterator for IntoIter { impl WeakKeyHashMap { /// Creates an empty `WeakKeyHashMap`. + /// + /// *O*(1) time pub fn new() -> Self { Self::with_capacity(DEFAULT_INITIAL_CAPACITY) } /// Creates an empty `WeakKeyHashMap` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_and_hasher(capacity, Default::default()) } @@ -207,11 +211,15 @@ impl WeakKeyHashMap impl WeakKeyHashMap { /// Creates an empty `WeakKeyHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { Self::with_capacity_and_hasher(DEFAULT_INITIAL_CAPACITY, hash_builder) } /// Creates an empty `WeakKeyHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { WeakKeyHashMap { hash_builder, @@ -223,11 +231,15 @@ impl WeakKeyHashMap } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { &self.hash_builder } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.inner.capacity() } @@ -250,17 +262,23 @@ impl WeakKeyHashMap } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.retain(|_, _| true) } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { let new_capacity = additional_capacity + self.capacity(); self.resize(new_capacity); } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.remove_expired(); let new_capacity = (self.len() as f32 / COLLECT_LOAD_FACTOR).ceil() as usize; @@ -268,6 +286,8 @@ impl WeakKeyHashMap } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.inner.len } @@ -276,6 +296,8 @@ impl WeakKeyHashMap /// /// Note that this may return false even if all keys in the map have /// expired, if they haven't been collected yet. + /// + /// *O*(1) time pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -283,6 +305,8 @@ impl WeakKeyHashMap /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired keys. + /// + /// *O*(1) time pub fn load_factor(&self) -> f32 { (self.len() as f32 + 1.0) / self.capacity() as f32 } @@ -302,6 +326,8 @@ impl WeakKeyHashMap } /// Gets the requested entry. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn entry(&mut self, key: K::Strong) -> Entry { self.maybe_adjust_size(); self.entry_no_grow(key) @@ -338,6 +364,8 @@ impl WeakKeyHashMap } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.drain(); } @@ -377,6 +405,8 @@ impl WeakKeyHashMap } /// Returns a reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &Q) -> Option<&V> where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -386,6 +416,8 @@ impl WeakKeyHashMap } /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains_key(&self, key: &Q) -> bool where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -394,6 +426,8 @@ impl WeakKeyHashMap } /// Returns a strong reference to the key, if found. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_key(&self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -402,6 +436,8 @@ impl WeakKeyHashMap } /// Returns a pair of a strong reference to the key, and a reference to the value, if present. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_both(&self, key: &Q) -> Option<(K::Strong, &V)> where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -411,6 +447,8 @@ impl WeakKeyHashMap } /// Returns a mutable reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -421,6 +459,8 @@ impl WeakKeyHashMap /// Returns a pair of a strong reference to the key, and a mutable reference to the value, /// if present. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_both_mut(&mut self, key: &Q) -> Option<(K::Strong, &mut V)> where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -432,6 +472,8 @@ impl WeakKeyHashMap /// Unconditionally inserts the value, returning the old value if already present. /// /// Unlike `std::collections::HashMap`, this replaced the key even if occupied. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: K::Strong, value: V) -> Option { match self.entry(key) { Entry::Occupied(mut occupied) => { @@ -445,6 +487,8 @@ impl WeakKeyHashMap } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -462,6 +506,8 @@ impl WeakKeyHashMap /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. + /// + /// *O*(*n*) time pub fn retain(&mut self, mut f: F) where F: FnMut(K::Strong, &mut V) -> bool { @@ -487,6 +533,10 @@ impl WeakKeyHashMap /// /// - `k` must also be a key of `other` and /// - `cmp(self[k], other[k])` must hold. + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap_with(&self, other: &WeakKeyHashMap, mut cmp: F) -> bool where F: FnMut(&V, &V1) -> bool, @@ -506,6 +556,10 @@ impl WeakKeyHashMap } /// Is `self` a submap of `other`? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap(&self, other: &WeakKeyHashMap) -> bool where V: PartialEq, S1: BuildHasher @@ -514,6 +568,10 @@ impl WeakKeyHashMap } /// Are the keys of `self` a subset of the keys of `other`? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn domain_is_subset(&self, other: &WeakKeyHashMap) -> bool where S1: BuildHasher { @@ -639,6 +697,8 @@ impl<'a, K: WeakKey, V> Entry<'a, K, V> { /// Ensures a value is in the entry by inserting a default value /// if empty, and returns a mutable reference to the value in the /// entry. + /// + /// *O*(1) time pub fn or_insert(self, default: V) -> &'a mut V { self.or_insert_with(|| default) } @@ -646,6 +706,8 @@ impl<'a, K: WeakKey, V> Entry<'a, K, V> { /// Ensures a value is in the entry by inserting the result of the /// default function if empty, and returns a mutable reference to /// the value in the entry. + /// + /// *O*(1) time pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Entry::Occupied(occupied) => occupied.into_mut(), @@ -654,6 +716,8 @@ impl<'a, K: WeakKey, V> Entry<'a, K, V> { } /// Returns a reference to this entry's key. + /// + /// *O*(1) time pub fn key(&self) -> &K::Strong { match *self { Entry::Occupied(ref occupied) => occupied.key(), @@ -664,11 +728,15 @@ impl<'a, K: WeakKey, V> Entry<'a, K, V> { impl<'a, K: WeakKey, V> OccupiedEntry<'a, K, V> { /// Gets a reference to the key held by the entry. + /// + /// *O*(1) time pub fn key(&self) -> &K::Strong { &self.0.key } /// Takes ownership of the key and value from the map. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove_entry(self) -> (K::Strong, V) { let (_, value, _) = self.0.map.buckets[self.0.pos].take().unwrap(); self.0.map.remove_index(self.0.pos); @@ -676,21 +744,29 @@ impl<'a, K: WeakKey, V> OccupiedEntry<'a, K, V> { } /// Gets a reference to the value in the entry. + /// + /// *O*(1) time pub fn get(&self) -> &V { &self.0.map.buckets[self.0.pos].as_ref().unwrap().1 } /// Gets a mutable reference to the value in the entry. + /// + /// *O*(1) time pub fn get_mut(&mut self) -> &mut V { &mut self.0.map.buckets[self.0.pos].as_mut().unwrap().1 } /// Turns the entry into a mutable reference to the value borrowed from the map. + /// + /// *O*(1) time pub fn into_mut(self) -> &'a mut V { &mut self.0.map.buckets[self.0.pos].as_mut().unwrap().1 } /// Replaces the value in the entry with the given value. + /// + /// *O*(1) time pub fn insert(&mut self, mut value: V) -> V { self.0.map.buckets[self.0.pos].as_mut().unwrap().0 = K::new(&self.0.key); mem::swap(self.get_mut(), &mut value); @@ -698,6 +774,8 @@ impl<'a, K: WeakKey, V> OccupiedEntry<'a, K, V> { } /// Removes the entry, returning the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(self) -> V { self.remove_entry().1 } @@ -706,17 +784,23 @@ impl<'a, K: WeakKey, V> OccupiedEntry<'a, K, V> { impl<'a, K: WeakKey, V> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a /// value through the `VacantEntry`. + /// + /// *O*(1) time pub fn key(&self) -> &K::Strong { &self.0.key } /// Returns ownership of the key. + /// + /// *O*(1) time pub fn into_key(self) -> K::Strong { self.0.key } /// Inserts the key and value into the map and return a mutable /// reference to the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(self, value: V) -> &'a mut V { let old_bucket = mem::replace( &mut self.0.map.buckets[self.0.pos], @@ -926,6 +1010,9 @@ impl IntoIterator for WeakKeyHashMap { type Item = (K::Strong, V); type IntoIter = IntoIter; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { IntoIter { size: self.inner.len, @@ -938,6 +1025,9 @@ impl<'a, K: WeakElement, V, S> IntoIterator for &'a WeakKeyHashMap { type Item = (K::Strong, &'a V); type IntoIter = Iter<'a, K, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { Iter { base: self.inner.buckets.iter(), @@ -950,6 +1040,9 @@ impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut WeakKeyHashMap type Item = (K::Strong, &'a mut V); type IntoIter = IterMut<'a, K, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { IterMut { base: self.inner.buckets.iter_mut(), @@ -960,31 +1053,43 @@ impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut WeakKeyHashMap impl WeakKeyHashMap { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter { self.into_iter() } /// Gets an iterator over the keys. + /// + /// *O*(1) time pub fn keys(&self) -> Keys { Keys(self.iter()) } /// Gets an iterator over the values. + /// + /// *O*(1) time pub fn values(&self) -> Values { Values(self.iter()) } /// Gets an iterator over the keys and mutable values. + /// + /// *O*(1) time pub fn iter_mut(&mut self) -> IterMut { self.into_iter() } /// Gets an iterator over the mutable values. + /// + /// *O*(1) time pub fn values_mut(&mut self) -> ValuesMut { ValuesMut(self.iter_mut()) } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain { let old_len = self.inner.len; self.inner.len = 0; diff --git a/src/weak_value_hash_map.rs b/src/weak_value_hash_map.rs index 78bf718..7177e41 100644 --- a/src/weak_value_hash_map.rs +++ b/src/weak_value_hash_map.rs @@ -155,11 +155,15 @@ impl Iterator for IntoIter { impl WeakValueHashMap { /// Creates an empty `WeakValueHashMap`. + /// + /// *O*(1) time pub fn new() -> Self { Self::with_capacity(DEFAULT_INITIAL_CAPACITY) } /// Creates an empty `WeakValueHashMap` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_and_hasher(capacity, Default::default()) } @@ -168,11 +172,15 @@ impl WeakValueHashMap impl WeakValueHashMap { /// Creates an empty `WeakValueHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { Self::with_capacity_and_hasher(DEFAULT_INITIAL_CAPACITY, hash_builder) } /// Creates an empty `WeakValueHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { WeakValueHashMap { hash_builder, @@ -184,11 +192,15 @@ impl WeakValueHashMap } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { &self.hash_builder } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.inner.capacity() } @@ -211,17 +223,23 @@ impl WeakValueHashMap } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.retain(|_, _| true) } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { let new_capacity = additional_capacity + self.capacity(); self.resize(new_capacity); } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.remove_expired(); let new_capacity = (self.len() as f32 / COLLECT_LOAD_FACTOR).ceil() as usize; @@ -229,6 +247,8 @@ impl WeakValueHashMap } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.inner.len } @@ -237,6 +257,8 @@ impl WeakValueHashMap /// /// Note that this may return false even if all keys in the map have /// expired, if they haven't been collected yet. + /// + /// *O*(1) time pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -244,6 +266,8 @@ impl WeakValueHashMap /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired keys. + /// + /// *O*(1) time pub fn load_factor(&self) -> f32 { (self.len() as f32 + 1.0) / self.capacity() as f32 } @@ -263,6 +287,8 @@ impl WeakValueHashMap } /// Gets the requested entry. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn entry(&mut self, key: K) -> Entry { self.maybe_adjust_size(); self.entry_no_grow(key) @@ -300,6 +326,8 @@ impl WeakValueHashMap } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.drain(); } @@ -339,6 +367,8 @@ impl WeakValueHashMap } /// Returns a reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K: Borrow @@ -347,6 +377,8 @@ impl WeakValueHashMap } /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains_key(&self, key: &Q) -> bool where Q: ?Sized + Hash + Eq, K: Borrow @@ -357,6 +389,8 @@ impl WeakValueHashMap /// Unconditionally inserts the value, returning the old value if already present. /// /// Like `std::collections::HashMap`, this does not replace the key if occupied. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: K, value: V::Strong) -> Option { match self.entry(key) { Entry::Occupied(mut occupied) => { @@ -370,6 +404,8 @@ impl WeakValueHashMap } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K: Borrow @@ -385,6 +421,8 @@ impl WeakValueHashMap /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. + /// + /// *O*(*n*) time pub fn retain(&mut self, mut f: F) where F: FnMut(&K, V::Strong) -> bool { @@ -408,6 +446,10 @@ impl WeakValueHashMap /// /// In particular, all the keys of `self` must be in `other` and the values must compare /// `true` with `value_equal`. + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap_with(&self, other: &WeakValueHashMap, mut value_equal: F) -> bool where V1: WeakElement, @@ -428,6 +470,10 @@ impl WeakValueHashMap } /// Is `self` a submap of `other`? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap(&self, other: &WeakValueHashMap) -> bool where V1: WeakElement, V::Strong: PartialEq, @@ -437,6 +483,10 @@ impl WeakValueHashMap } /// Are the keys of `self` a subset of the keys of `other`? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn domain_is_subset(&self, other: &WeakValueHashMap) -> bool where V1: WeakElement, S1: BuildHasher @@ -545,12 +595,16 @@ impl<'a, K: Eq + Hash, V: WeakElement> InnerEntry<'a, K, V> { impl<'a, K, V: WeakElement> Entry<'a, K, V> { /// Ensures a value is in the entry by inserting a default value /// if empty. + /// + /// *O*(1) time pub fn or_insert(self, default: V::Strong) -> V::Strong { self.or_insert_with(|| default) } /// Ensures a value is in the entry by inserting the result of the /// default function if empty. + /// + /// *O*(1) time pub fn or_insert_with V::Strong>(self, default: F) -> V::Strong { match self { Entry::Occupied(occupied) => occupied.get_strong(), @@ -559,6 +613,8 @@ impl<'a, K, V: WeakElement> Entry<'a, K, V> { } /// Returns a reference to this entry's key. + /// + /// *O*(1) time pub fn key(&self) -> &K { match *self { Entry::Occupied(ref occupied) => occupied.key(), @@ -569,11 +625,15 @@ impl<'a, K, V: WeakElement> Entry<'a, K, V> { impl<'a, K, V: WeakElement> OccupiedEntry<'a, K, V> { /// Gets a reference to the key held by the entry. + /// + /// *O*(1) time pub fn key(&self) -> &K { &self.inner.key } /// Takes ownership of the key and value from the map. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove_entry(self) -> (K, V::Strong) { let (key, w_value, _) = self.inner.map.buckets[self.inner.pos].take().unwrap(); let value = w_value.view().unwrap(); @@ -582,22 +642,30 @@ impl<'a, K, V: WeakElement> OccupiedEntry<'a, K, V> { } /// Gets a reference to the value in the entry. + /// + /// *O*(1) time pub fn get(&self) -> &V::Strong { &self.value } /// Gets a copy of the strong value reference stored in the entry. + /// + /// *O*(1) time pub fn get_strong(&self) -> V::Strong { V::clone(&self.value) } /// Replaces the value in the entry with the given value, returning the old value. + /// + /// *O*(1) time pub fn insert(&mut self, value: V::Strong) -> V::Strong { self.inner.map.buckets[self.inner.pos].as_mut().unwrap().1 = V::new(&value); mem::replace(&mut self.value, value) } /// Removes the entry, returning the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(self) -> V::Strong { self.remove_entry().1 } @@ -606,16 +674,22 @@ impl<'a, K, V: WeakElement> OccupiedEntry<'a, K, V> { impl<'a, K, V: WeakElement> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a /// value through the `VacantEntry`. + /// + /// *O*(1) time pub fn key(&self) -> &K { &self.inner.key } /// Returns ownership of the key. + /// + /// *O*(1) time pub fn into_key(self) -> K { self.inner.key } /// Inserts the value into the map, returning the same value. + /// + /// *O*(1) time pub fn insert(self, value: V::Strong) -> V::Strong { let InnerEntry { map, key, hash_code, pos } = self.inner; @@ -827,6 +901,9 @@ impl IntoIterator for WeakValueHashMap { type Item = (K, V::Strong); type IntoIter = IntoIter; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { IntoIter { size: self.inner.len, @@ -839,6 +916,9 @@ impl<'a, K, V: WeakElement, S> IntoIterator for &'a WeakValueHashMap { type Item = (&'a K, V::Strong); type IntoIter = Iter<'a, K, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { Iter { base: self.inner.buckets.iter(), @@ -849,21 +929,29 @@ impl<'a, K, V: WeakElement, S> IntoIterator for &'a WeakValueHashMap { impl WeakValueHashMap { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter { self.into_iter() } /// Gets an iterator over the keys. + /// + /// *O*(1) time pub fn keys(&self) -> Keys { Keys(self.iter()) } /// Gets an iterator over the values. + /// + /// *O*(1) time pub fn values(&self) -> Values { Values(self.iter()) } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain { let old_len = self.inner.len; self.inner.len = 0; diff --git a/src/weak_weak_hash_map.rs b/src/weak_weak_hash_map.rs index 29df15b..801bc64 100644 --- a/src/weak_weak_hash_map.rs +++ b/src/weak_weak_hash_map.rs @@ -156,11 +156,15 @@ impl Iterator for IntoIter { impl WeakWeakHashMap { /// Creates an empty `WeakWeakHashMap`. + /// + /// *O*(1) time pub fn new() -> Self { Self::with_capacity(DEFAULT_INITIAL_CAPACITY) } /// Creates an empty `WeakWeakHashMap` with the given capacity. + /// + /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_and_hasher(capacity, Default::default()) } @@ -168,11 +172,15 @@ impl WeakWeakHashMap impl WeakWeakHashMap { /// Creates an empty `WeakWeakHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { Self::with_capacity_and_hasher(DEFAULT_INITIAL_CAPACITY, hash_builder) } /// Creates an empty `WeakWeakHashMap` with the given capacity and hasher. + /// + /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { WeakWeakHashMap { hash_builder, @@ -184,11 +192,15 @@ impl WeakWeakHashMap { } /// Returns a reference to the map's `BuildHasher`. + /// + /// *O*(1) time pub fn hasher(&self) -> &S { &self.hash_builder } /// Returns the number of elements the map can hold without reallocating. + /// + /// *O*(1) time pub fn capacity(&self) -> usize { self.inner.capacity() } @@ -211,17 +223,23 @@ impl WeakWeakHashMap { } /// Removes all mappings whose keys have expired. + /// + /// *O*(*n*) time pub fn remove_expired(&mut self) { self.retain(|_, _| true) } /// Reserves room for additional elements. + /// + /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { let new_capacity = additional_capacity + self.capacity(); self.resize(new_capacity); } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. + /// + /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.remove_expired(); let new_capacity = (self.len() as f32 / COLLECT_LOAD_FACTOR).ceil() as usize; @@ -229,6 +247,8 @@ impl WeakWeakHashMap { } /// Returns an over-approximation of the number of elements. + /// + /// *O*(1) time pub fn len(&self) -> usize { self.inner.len } @@ -237,6 +257,8 @@ impl WeakWeakHashMap { /// /// Note that this may return false even if all keys in the map have /// expired, if they haven't been collected yet. + /// + /// *O*(1) time pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -244,6 +266,8 @@ impl WeakWeakHashMap { /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired keys. + /// + /// *O*(1) time pub fn load_factor(&self) -> f32 { (self.len() as f32 + 1.0) / self.capacity() as f32 } @@ -263,6 +287,10 @@ impl WeakWeakHashMap { } /// Gets the requested entry. + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn entry(&mut self, key: K::Strong) -> Entry { self.maybe_adjust_size(); self.entry_no_grow(key) @@ -299,6 +327,8 @@ impl WeakWeakHashMap { } /// Removes all associations from the map. + /// + /// *O*(*n*) time pub fn clear(&mut self) { self.drain(); } @@ -338,6 +368,8 @@ impl WeakWeakHashMap { } /// Returns a reference to the value corresponding to the key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -346,6 +378,8 @@ impl WeakWeakHashMap { } /// Returns the strong reference to the key, if present. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_key(&self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -354,6 +388,8 @@ impl WeakWeakHashMap { } /// Returns strong references to both the key and the value, if present. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_both(&self, key: &Q) -> Option<(K::Strong, V::Strong)> where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -362,6 +398,8 @@ impl WeakWeakHashMap { } /// Returns true if the map contains the specified key. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains_key(&self, key: &Q) -> bool where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -372,6 +410,8 @@ impl WeakWeakHashMap { /// Unconditionally inserts the value, returning the old value if already present. /// /// Unlike `std::collections::HashMap`, this replaces the key even if occupied. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: K::Strong, value: V::Strong) -> Option { match self.entry(key) { Entry::Occupied(mut occupied) => { @@ -385,6 +425,8 @@ impl WeakWeakHashMap { } /// Removes the entry with the given key, if it exists, and returns the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &Q) -> Option where Q: ?Sized + Hash + Eq, K::Key: Borrow @@ -400,6 +442,8 @@ impl WeakWeakHashMap { /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. + /// + /// *O*(*n*) time pub fn retain(&mut self, mut f: F) where F: FnMut(K::Strong, V::Strong) -> bool { @@ -423,6 +467,10 @@ impl WeakWeakHashMap { /// /// In particular, all the keys of `self` must be in `other` and the values must compare /// `true` with `value_equal`. + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap_with(&self, other: &WeakWeakHashMap, mut value_equal: F) -> bool where V1: WeakElement, @@ -443,6 +491,10 @@ impl WeakWeakHashMap { } /// Is `self` a submap of `other`? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn is_submap(&self, other: &WeakWeakHashMap) -> bool where V1: WeakElement, V::Strong: PartialEq, @@ -452,6 +504,10 @@ impl WeakWeakHashMap { } /// Are the keys of `self` a subset of the keys of `other`? + /// + /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is + /// `self.capacity()` and *q* is the length of the probe sequences + /// in `other`) pub fn domain_is_subset(&self, other: &WeakWeakHashMap) -> bool where V1: WeakElement, S1: BuildHasher @@ -547,6 +603,8 @@ impl<'a, K: WeakKey, V: WeakElement> Entry<'a, K, V> { /// Ensures a value is in the entry by inserting a default value /// if empty, and returns a mutable reference to the value in the /// entry. + /// + /// *O*(1) time pub fn or_insert(self, default: V::Strong) -> V::Strong { self.or_insert_with(|| default) } @@ -554,6 +612,8 @@ impl<'a, K: WeakKey, V: WeakElement> Entry<'a, K, V> { /// Ensures a value is in the entry by inserting the result of the /// default function if empty, and returns a mutable reference to /// the value in the entry. + /// + /// *O*(1) time pub fn or_insert_with V::Strong>(self, default: F) -> V::Strong { match self { Entry::Occupied(occupied) => occupied.get_strong(), @@ -562,6 +622,8 @@ impl<'a, K: WeakKey, V: WeakElement> Entry<'a, K, V> { } /// Returns a reference to this entry's key. + /// + /// *O*(1) time pub fn key(&self) -> &K::Strong { match *self { Entry::Occupied(ref occupied) => occupied.key(), @@ -572,11 +634,15 @@ impl<'a, K: WeakKey, V: WeakElement> Entry<'a, K, V> { impl<'a, K: WeakKey, V: WeakElement> OccupiedEntry<'a, K, V> { /// Gets a reference to the key held by the entry. + /// + /// *O*(1) time pub fn key(&self) -> &K::Strong { &self.inner.key } /// Takes ownership of the key and value from the map. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove_entry(self) -> (K::Strong, V::Strong) { let (_, w_value, _) = self.inner.map.buckets[self.inner.pos].take().unwrap(); let value = w_value.view().unwrap(); @@ -585,22 +651,30 @@ impl<'a, K: WeakKey, V: WeakElement> OccupiedEntry<'a, K, V> { } /// Gets a reference to the value in the entry. + /// + /// *O*(1) time pub fn get(&self) -> &V::Strong { &self.value } /// Gets a clone of the reference to the value in the entry. + /// + /// *O*(1) time pub fn get_strong(&self) -> V::Strong { V::clone(&self.value) } /// Replaces the value in the entry with the given value. + /// + /// *O*(1) time pub fn insert(&mut self, value: V::Strong) -> V::Strong { self.inner.map.buckets[self.inner.pos].as_mut().unwrap().1 = V::new(&value); mem::replace(&mut self.value, value) } /// Removes the entry, returning the value. + /// + /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(self) -> V::Strong { self.remove_entry().1 } @@ -609,16 +683,22 @@ impl<'a, K: WeakKey, V: WeakElement> OccupiedEntry<'a, K, V> { impl<'a, K: WeakKey, V: WeakElement> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a /// value through the `VacantEntry`. + /// + /// *O*(1) time pub fn key(&self) -> &K::Strong { &self.inner.key } /// Returns ownership of the key. + /// + /// *O*(1) time pub fn into_key(self) -> K::Strong { self.inner.key } /// Inserts the key and value into the map, returning the same value. + /// + /// *O*(1) time pub fn insert(self, value: V::Strong) -> V::Strong { let old_bucket = mem::replace( &mut self.inner.map.buckets[self.inner.pos], @@ -843,6 +923,9 @@ impl IntoIterator for WeakWeakHashMap; + /// Creates an owning iterator from `self`. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { IntoIter { size: self.inner.len, @@ -855,6 +938,9 @@ impl<'a, K: WeakElement, V: WeakElement, S> IntoIterator for &'a WeakWeakHashMap type Item = (K::Strong, V::Strong); type IntoIter = Iter<'a, K, V>; + /// Creates a borrowing iterator from `self`. + /// + /// *O*(1) time fn into_iter(self) -> Self::IntoIter { Iter { base: self.inner.buckets.iter(), @@ -865,21 +951,29 @@ impl<'a, K: WeakElement, V: WeakElement, S> IntoIterator for &'a WeakWeakHashMap impl WeakWeakHashMap { /// Gets an iterator over the keys and values. + /// + /// *O*(1) time pub fn iter(&self) -> Iter { self.into_iter() } /// Gets an iterator over the keys. + /// + /// *O*(1) time pub fn keys(&self) -> Keys { Keys(self.iter()) } /// Gets an iterator over the values. + /// + /// *O*(1) time pub fn values(&self) -> Values { Values(self.iter()) } /// Gets a draining iterator, which removes all the values but retains the storage. + /// + /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain { let old_len = self.inner.len; self.inner.len = 0;