weak-table-0.3.2/.cargo_vcs_info.json0000644000000001120000000000100130440ustar { "git": { "sha1": "c4ac207b8f266ff3becd123f693f07536b97d088" } } weak-table-0.3.2/.github/dependabot.yml000064400000000000000000000002210072674642500160550ustar 00000000000000version: 2 updates: - package-ecosystem: cargo directory: "/" schedule: interval: daily time: "11:00" open-pull-requests-limit: 10 weak-table-0.3.2/.github/workflows/ci.yml000064400000000000000000000031000072674642500163770ustar 00000000000000on: [push, pull_request] name: CI jobs: check: name: Check runs-on: ubuntu-latest strategy: matrix: rust: - stable - 1.46.0 features: - --features=std - --no-default-features --features=alloc,ahash steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - uses: actions-rs/cargo@v1 with: command: check args: --all-targets ${{ matrix.features }} test: name: Test Suite runs-on: ubuntu-latest strategy: matrix: rust: - stable - 1.46.0 features: - --features=std - --no-default-features --features=alloc,ahash steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - uses: actions-rs/cargo@v1 with: command: test args: ${{ matrix.features }} clippy: name: Clippy runs-on: ubuntu-latest strategy: matrix: rust: - stable - 1.46.0 steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - run: rustup component add clippy - uses: actions-rs/cargo@v1 with: command: clippy args: -- -D warnings weak-table-0.3.2/.gitignore000064400000000000000000000004220072674642500136600ustar 00000000000000# Generated by Cargo # will have compiled files and executables /target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock Cargo.lock /.idea/ /cmake-build-*/ weak-table-0.3.2/CHANGELOG.md000064400000000000000000000042620072674642500135070ustar 00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog] and this project adheres to [Semantic Versioning]. [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ [Semantic Versioning]: http://semver.org/spec/v2.0.0.html ## [Next Release] ## [0.3.2] - 2021-12-01 ## [0.3.1] - 2021-11-30 ### Added - `no_std` compatibility (h/t @tsao-chi) ## [0.2.4] - 2020-06-27 ### Fixed - Bad bucket selection on collision (h/t Andrew Browne ``). ## [0.2.3] - 2018-05-30 ### Fixed - Use `Rc::ptr_eq` to compare `Rc`s by address. ## [0.2.2] - 2018-05-22 ### Fixed - Weak–weak submap operations were missing a line of code. ### Added - `{PtrWeakHashSet,PtrWeakKeyHashMap}::is_empty()` methods. ## [0.2.1] - 2018-05-22 ### Fixed - documentation - a test that was breaking on an older `rustc` ## [0.2.0] - 2018-05-22 ### Renamed - from `WeakElement::expired` to `WeakElement::is_expired` ### Improved - documentation ## [0.1.3] - 2018-05-22 ### Added - documentation of minimum supported `rustc` - a test ## [0.1.2] - 2018-05-21 ### Added - `WeakKeyHashMap::{get_key, get_both, get_both_mut}` methods - `WeakWeakHashMap::{get_key, get_both}` methods - `WeakHashSet::get` method ### Changed - Values stored behind `Rc`s can now be `?Sized`. ### Removed - `struct RcKey` ### Improved - documentation ## [0.1.1] - 2018-03-05 Initial release. [Next Release]: [0.3.2]: [0.3.1]: [0.2.4]: [0.2.3]: [0.2.2]: [0.2.1]: [0.2.0]: [0.1.3]: [0.1.2]: [0.1.1]: weak-table-0.3.2/CMakeLists.txt000064400000000000000000000000510072674642500144260ustar 00000000000000# This file is here to make CLion happy. weak-table-0.3.2/Cargo.toml0000644000000017150000000000100110540ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "weak-table" version = "0.3.2" authors = ["Jesse A. Tov "] description = "Weak hash maps and sets" readme = "README.md" keywords = ["containers", "Rc", "Arc", "weak", "no_std"] license = "MIT" repository = "https://github.com/tov/weak-table-rs" [dependencies.ahash] version = "0.7.6" features = [] optional = true [dev-dependencies.quickcheck] version = "1" [dev-dependencies.rand] version = "0.8.4" [features] alloc = [] default = ["std"] std = [] weak-table-0.3.2/Cargo.toml.orig000064400000000000000000000010460072674642500145620ustar 00000000000000[package] name = "weak-table" version = "0.3.2" authors = ["Jesse A. Tov "] description = "Weak hash maps and sets" repository = "https://github.com/tov/weak-table-rs" readme = "README.md" license = "MIT" keywords = ["containers", "Rc", "Arc", "weak", "no_std"] edition = "2018" [dependencies] ahash = { version = "0.7.6", optional = true, features = [] } [dev-dependencies] quickcheck = "1" rand = "0.8.4" [features] default = ["std"] std = [] # This feature doesn’t actually do anything. TODO: remove in v0.4. alloc = [] weak-table-0.3.2/LICENSE000064400000000000000000000020550072674642500127010ustar 00000000000000MIT License Copyright (c) 2018 Jesse A. Tov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. weak-table-0.3.2/Makefile000064400000000000000000000006200072674642500133300ustar 00000000000000default: build hard: test CRATE = weak_table REPO = weak-table-rs build: clear cargo build make doc clippy: rustup run nightly cargo build --features=clippy doc: cargo doc echo "" > target/doc/index.html test: clear cargo test upload-doc: make doc ghp-import -n target/doc git push -f https://github.com/tov/$(REPO).git gh-pages weak-table-0.3.2/README.md000064400000000000000000000052260072674642500131560ustar 00000000000000# weak-table: weak hash maps and sets for Rust [![Build Status](https://github.com/tov/weak-table-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/tov/weak-table-rs/actions) [![Crates.io](https://img.shields.io/crates/v/weak-table.svg?maxAge=2592000)](https://crates.io/crates/weak-table) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT) This crate defines several kinds of weak hash maps and sets. See the [full API documentation](http://docs.rs/weak-table/) for details. ### Rust version support This crate supports Rust version 1.46 and later. ### 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. ### Examples Here we create a weak hash map and demonstrate that it forgets mappings whose keys expire: ```rust use weak_table::WeakKeyHashMap; use std::sync::{Arc, Weak}; let mut table = , u32>>::new(); let one = Arc::::from("one"); let two = Arc::::from("two"); table.insert(one.clone(), 1); assert_eq!( table.get("one"), Some(&1) ); assert_eq!( table.get("two"), None ); table.insert(two.clone(), 2); *table.get_mut(&one).unwrap() += 10; assert_eq!( table.get("one"), Some(&11) ); assert_eq!( table.get("two"), Some(&2) ); drop(one); assert_eq!( table.get("one"), None ); assert_eq!( table.get("two"), Some(&2) ); ``` Here we use a weak hash set to implement a simple string interning facility: ```rust use weak_table::WeakHashSet; use std::ops::Deref; use std::rc::{Rc, Weak}; #[derive(Clone, Debug)] pub struct Symbol(Rc); impl PartialEq for Symbol { fn eq(&self, other: &Symbol) -> bool { Rc::ptr_eq(&self.0, &other.0) } } impl Eq for Symbol {} impl Deref for Symbol { type Target = str; fn deref(&self) -> &str { &self.0 } } #[derive(Debug, Default)] pub struct SymbolTable(WeakHashSet>); impl SymbolTable { pub fn new() -> Self { Self::default() } pub fn intern(&mut self, name: &str) -> Symbol { if let Some(rc) = self.0.get(name) { Symbol(rc) } else { let rc = Rc::::from(name); self.0.insert(Rc::clone(&rc)); Symbol(rc) } } } #[test] fn interning() { let mut tab = SymbolTable::new(); let a0 = tab.intern("a"); let a1 = tab.intern("a"); let b = tab.intern("b"); assert_eq!(a0, a1); assert_ne!(a0, b); } ``` weak-table-0.3.2/release.toml000064400000000000000000000013170072674642500142110ustar 00000000000000tag-name = "v{{version}}" [[pre-release-replacements]] file = "src/lib.rs" search = "https://docs[.]rs/weak-table/[0-9.]*" replace = "https://docs.rs/weak-table/{{version}}" [[pre-release-replacements]] file = "CHANGELOG.md" search = "## \\[Next Release\\]" replace = "## [Next Release]\n\n## [{{version}}] - {{date}}" [[pre-release-replacements]] file = "CHANGELOG.md" search = "\\[Next Release\\]: " replace = '''[Next Release]: [{{version}}]: ''' weak-table-0.3.2/src/by_ptr.rs000064400000000000000000000013060072674642500143260ustar 00000000000000use crate::compat::*; use super::traits::*; /// Wrapper struct for using pointer equality and hashes rather /// than pointed-to value equality and hashes. #[derive(Clone, Debug)] pub struct ByPtr(K); impl WeakElement for ByPtr { type Strong = K::Strong; fn new(view: &Self::Strong) -> Self { ByPtr(K::new(view)) } fn view(&self) -> Option { self.0.view() } } impl WeakKey for ByPtr where K::Strong: Deref { type Key = *const ::Target; fn with_key(view: &Self::Strong, f: F) -> R where F: FnOnce(&Self::Key) -> R { f(&(view.deref() as *const _)) } } weak-table-0.3.2/src/compat.rs000064400000000000000000000024500072674642500143130ustar 00000000000000//! `no_std` compatibility // If we depend on `ahash`, use its hasher. #[cfg(feature = "ahash")] pub use ahash::RandomState; // Use the `std` hasher if we don’t depend on `ahash` but do depend on // `std`. #[cfg(all(not(feature = "ahash"), feature = "std"))] pub use std::collections::hash_map::RandomState; // If we depend on neither `ahash` nor `std` then it’s an error. #[cfg(not(any(feature = "ahash", feature = "std")))] compile_error!("weak-table: no_std requires that you enable the `ahash` feature."); // If we depend on `std`, alias `lib` to `std`. #[cfg(feature = "std")] mod lib { extern crate std; pub use std::*; } // Otherwise, we are `no_std`, so alias `lib` to `alloc`. #[cfg(not(feature = "std"))] mod lib { extern crate alloc; pub use alloc::*; } // Stuff from `std`/`alloc` that we use often. pub use lib::{ boxed::Box, rc, slice, string::String, sync, vec::{self, Vec}, }; // Stuff from `core` that we use often: pub use core::{ borrow::Borrow, cmp::max, hash::{BuildHasher, Hash, Hasher}, iter::{self, FromIterator}, fmt::{self, Debug, Formatter}, mem, ops::{self, Deref, Index, IndexMut}, }; // When testing, we need the `eprintln` macro from `std`: #[cfg(test)] extern crate std; #[cfg(test)] pub use std::eprintln; weak-table-0.3.2/src/lib.rs000064400000000000000000000166460072674642500136120ustar 00000000000000//! This library offers a variety of weak hash tables: //! //! - For a hash map where the keys are held by weak pointers and compared by key value, see //! [`WeakKeyHashMap`](struct.WeakKeyHashMap.html). //! //! - For a hash map where the keys are held by weak pointers and compared by pointer, see //! [`PtrWeakKeyHashMap`](struct.PtrWeakKeyHashMap.html). //! //! - For a hash map where the values are held by weak pointers, see //! [`WeakValueHashMap`](struct.WeakValueHashMap.html). //! //! - For a hash map where the keys and values are both held by weak pointers and the keys are //! compared by value, see //! [`WeakWeakHashMap`](struct.WeakWeakHashMap.html). //! //! - For a hash map where the keys and values are both held by weak pointers and the keys are //! compared by pointer, see //! [`PtrWeakWeakHashMap`](struct.PtrWeakWeakHashMap.html). //! //! - For a hash set where the elements are held by weak pointers and compared by element value, see //! [`WeakHashSet`](struct.WeakHashSet.html). //! //! - For a hash set where the elements are held by weak pointers and compared by pointer, see //! [`PtrWeakHashSet`](struct.PtrWeakHashSet.html). //! //! 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. //! //! ## 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 //! //! Note that *p* ∈ *O*(*n*), but we expect it to be *O*(1). //! //! # 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. //! //! # Examples //! //! Here we create a weak hash table mapping strings to integers. //! Note that after dropping `one`, the key `"one"` is no longer present in the map. //! This is because the map holds the strings as `std::sync::Weak`s. //! //! ``` //! use weak_table::WeakKeyHashMap; //! use std::sync::{Arc, Weak}; //! //! let mut table = , u32>>::new(); //! let one = Arc::::from("one"); //! let two = Arc::::from("two"); //! //! table.insert(one.clone(), 1); //! //! assert_eq!( table.get("one"), Some(&1) ); //! assert_eq!( table.get("two"), None ); //! //! table.insert(two.clone(), 2); //! *table.get_mut(&one).unwrap() += 10; //! //! assert_eq!( table.get("one"), Some(&11) ); //! assert_eq!( table.get("two"), Some(&2) ); //! //! drop(one); //! //! assert_eq!( table.get("one"), None ); //! assert_eq!( table.get("two"), Some(&2) ); //! ``` //! //! Here we use a weak hash set to implement a simple string interning facility: //! //! ``` //! use weak_table::WeakHashSet; //! use std::ops::Deref; //! use std::rc::{Rc, Weak}; //! //! #[derive(Clone, Debug)] //! pub struct Symbol(Rc); //! //! impl PartialEq for Symbol { //! fn eq(&self, other: &Symbol) -> bool { //! Rc::ptr_eq(&self.0, &other.0) //! } //! } //! //! impl Eq for Symbol {} //! //! impl Deref for Symbol { //! type Target = str; //! fn deref(&self) -> &str { //! &self.0 //! } //! } //! //! #[derive(Debug, Default)] //! pub struct SymbolTable(WeakHashSet>); //! //! impl SymbolTable { //! pub fn new() -> Self { //! Self::default() //! } //! //! pub fn intern(&mut self, name: &str) -> Symbol { //! if let Some(rc) = self.0.get(name) { //! Symbol(rc) //! } else { //! let rc = Rc::::from(name); //! self.0.insert(Rc::clone(&rc)); //! Symbol(rc) //! } //! } //! } //! //! #[test] //! fn interning() { //! let mut tab = SymbolTable::new(); //! //! let a0 = tab.intern("a"); //! let a1 = tab.intern("a"); //! let b = tab.intern("b"); //! //! assert_eq!(a0, a1); //! assert_ne!(a0, b); //! } //! ``` #![doc(html_root_url = "https://docs.rs/weak-table/0.3.2")] #![cfg_attr(not(feature = "std"), no_std)] use self::compat::*; pub mod traits; pub mod weak_key_hash_map; pub mod ptr_weak_key_hash_map; pub mod weak_value_hash_map; pub mod weak_weak_hash_map; pub mod ptr_weak_weak_hash_map; pub mod weak_hash_set; pub mod ptr_weak_hash_set; mod compat; mod util; mod by_ptr; mod size_policy; #[derive(Copy, Clone, Debug, PartialEq, Eq)] struct HashCode(u64); type FullBucket = (K, V, HashCode); type Bucket = Option>; type TablePtr = Box<[Bucket]>; /// A hash map with weak keys, hashed on key value. /// /// When a weak pointer expires, its mapping is lazily removed. #[derive(Clone)] pub struct WeakKeyHashMap { hash_builder: S, inner: WeakKeyInnerMap, } #[derive(Clone)] struct WeakKeyInnerMap { buckets: TablePtr, len: usize, } /// A hash map with weak keys, hashed on key pointer. /// /// When a weak pointer expires, its mapping is lazily removed. /// /// # Examples /// /// ``` /// use weak_table::PtrWeakKeyHashMap; /// use std::rc::{Rc, Weak}; /// /// type Table = PtrWeakKeyHashMap, usize>; /// /// let mut map = Table::new(); /// let a = Rc::::from("hello"); /// let b = Rc::::from("hello"); /// /// map.insert(a.clone(), 5); /// /// assert_eq!( map.get(&a), Some(&5) ); /// assert_eq!( map.get(&b), None ); /// /// map.insert(b.clone(), 7); /// /// assert_eq!( map.get(&a), Some(&5) ); /// assert_eq!( map.get(&b), Some(&7) ); /// ``` #[derive(Clone)] pub struct PtrWeakKeyHashMap( WeakKeyHashMap, V, S> ); /// A hash map with weak values. /// /// When a weak pointer expires, its mapping is lazily removed. #[derive(Clone)] pub struct WeakValueHashMap { hash_builder: S, inner: WeakValueInnerMap, } #[derive(Clone)] struct WeakValueInnerMap { buckets: TablePtr, len: usize, } /// A hash map with weak keys and weak values, hashed on key value. /// /// When a weak pointer expires, its mapping is lazily removed. #[derive(Clone)] pub struct WeakWeakHashMap { hash_builder: S, inner: WeakWeakInnerMap, } #[derive(Clone)] struct WeakWeakInnerMap { buckets: TablePtr, len: usize, } /// A hash map with weak keys and weak values, hashed on key pointer. /// /// When a weak pointer expires, its mapping is lazily removed. #[derive(Clone)] pub struct PtrWeakWeakHashMap( WeakWeakHashMap, V, S> ); /// A hash set with weak elements, hashed on element value. /// /// When a weak pointer expires, its mapping is lazily removed. #[derive(Clone)] pub struct WeakHashSet(WeakKeyHashMap); /// A hash set with weak elements, hashed on element pointer. /// /// When a weak pointer expires, its mapping is lazily removed. #[derive(Clone)] pub struct PtrWeakHashSet(PtrWeakKeyHashMap); weak-table-0.3.2/src/ptr_weak_hash_set.rs000064400000000000000000000174320072674642500165300ustar 00000000000000//! A hash set where the elements are held by weak pointers and compared by pointer. use crate::compat::*; use super::traits::*; use super::ptr_weak_key_hash_map as base; use super::by_ptr::ByPtr; pub use super::PtrWeakHashSet; 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)) } } 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() } /// Is the set known to be empty? /// /// 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 } /// 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() } /// 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 { self.0.retain(|k, _| f(k)) } /// 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 { self.0.domain_is_subset(&other.0) } } /// An iterator over the elements of a set. pub struct Iter<'a, T: 'a>(base::Keys<'a, ByPtr, ()>); impl<'a, T: WeakElement> Iterator for Iter<'a, T> { type Item = T::Strong; fn next(&mut self) -> Option { self.0.next() } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// An iterator over the elements of a set. pub struct IntoIter(base::IntoIter, ()>); impl Iterator for IntoIter { type Item = T::Strong; fn next(&mut self) -> Option { self.0.next().map(|pair| pair.0) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// A draining iterator over the elements of a set. pub struct Drain<'a, T: 'a>(base::Drain<'a, ByPtr, ()>); impl<'a, T: WeakElement> Iterator for Drain<'a, T> { type Item = T::Strong; fn next(&mut self) -> Option { self.0.next().map(|pair| pair.0) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } 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()) } } impl PartialEq> for PtrWeakHashSet where T: WeakElement, T::Strong: Deref, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &PtrWeakHashSet) -> bool { self.0 == other.0 } } impl Eq for PtrWeakHashSet where T::Strong: Deref { } impl Default for PtrWeakHashSet where T::Strong: Deref { fn default() -> Self { PtrWeakHashSet(base::PtrWeakKeyHashMap::::default()) } } impl FromIterator for PtrWeakHashSet where T: WeakElement, T::Strong: Deref, S: BuildHasher + Default { fn from_iter>(iter: I) -> Self { PtrWeakHashSet(base::PtrWeakKeyHashMap::::from_iter( iter.into_iter().map(|k| (k, ())))) } } impl Extend for PtrWeakHashSet where T: WeakElement, T::Strong: Deref, S: BuildHasher { fn extend>(&mut self, iter: I) { self.0.extend(iter.into_iter().map(|k| (k, ()))) } } impl Debug for PtrWeakHashSet where T: WeakElement, T::Strong: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } 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()) } } impl<'a, T: WeakElement, S> IntoIterator for &'a PtrWeakHashSet where T::Strong: Deref { 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()) } } weak-table-0.3.2/src/ptr_weak_key_hash_map.rs000064400000000000000000000272570072674642500173700ustar 00000000000000//! A hash map where the keys are held by weak pointers and compared by pointer. use crate::compat::*; use super::by_ptr::*; use super::traits::*; use super::weak_key_hash_map as base; pub use super::PtrWeakKeyHashMap; pub use super::weak_key_hash_map::{Entry, Iter, IterMut, Keys, Values, ValuesMut, Drain, IntoIter}; 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)) } } 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() } /// Is the map known to be empty? /// /// 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 } /// 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 _)) } /// 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 { self.0.retain(f) } /// Is this map a submap of the other, using the given value comparison. /// /// 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 { self.0.is_submap_with(&other.0, value_equal) } /// 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 { self.0.is_submap(&other.0) } /// 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 { self.0.domain_is_subset(&other.0) } } 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() } } impl PartialEq> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, V: PartialEq, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &PtrWeakKeyHashMap) -> bool { self.0 == other.0 } } impl Eq for PtrWeakKeyHashMap where K::Strong: Deref { } impl Default for PtrWeakKeyHashMap where K::Strong: Deref { fn default() -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::, V, S>::default()) } } impl<'a, K, V, S> Index<&'a K::Strong> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher { type Output = V; fn index(&self, index: &'a K::Strong) -> &Self::Output { self.0.index(&(index.deref() as *const _)) } } impl<'a, K, V, S> IndexMut<&'a K::Strong> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher { fn index_mut(&mut self, index: &'a K::Strong) -> &mut Self::Output { self.0.index_mut(&(index.deref() as *const _)) } } impl FromIterator<(K::Strong, V)> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher + Default { fn from_iter>(iter: T) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::, V, S>::from_iter(iter)) } } impl Extend<(K::Strong, V)> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher { fn extend>(&mut self, iter: T) { self.0.extend(iter) } } impl<'a, K, V, S> Extend<(&'a K::Strong, &'a V)> for PtrWeakKeyHashMap where K: 'a + WeakElement, K::Strong: Clone + Deref, V: 'a + Clone, S: BuildHasher { fn extend>(&mut self, iter: T) { self.0.extend(iter) } } impl Debug for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } 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() } } 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() } } impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut PtrWeakKeyHashMap { type Item = (K::Strong, &'a mut V); type IntoIter = IterMut<'a, ByPtr, V>; /// Creates a borrowing iterator from `self`. /// /// *O*(1) time fn into_iter(self) -> Self::IntoIter { (&mut self.0).into_iter() } } #[cfg(test)] mod test { use crate::compat::{ eprintln, rc::{Rc, Weak}, Vec, }; use super::{Entry, PtrWeakKeyHashMap}; // fn show_me(weakmap: &PtrWeakKeyHashMap, f32>) { // for (key, _) in weakmap { // eprint!(" {:2}", *key); // } // eprintln!(); // } // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060 #[test] fn insert_and_check() { let mut rcs: Vec> = Vec::new(); for i in 0 .. 200 { rcs.push(Rc::new(i)); } let mut weakmap: PtrWeakKeyHashMap, f32> = PtrWeakKeyHashMap::new(); for item in rcs.iter().cloned() { let f = *item as f32 + 0.1; weakmap.insert(item, f); } let mut count = 0; for item in &rcs { assert!(weakmap.contains_key(item)); match weakmap.entry(Rc::clone(item)) { Entry::Occupied(_) => count += 1, Entry::Vacant(_) => eprintln!("PointerWeakKeyHashMap: missing: {}", *item), } } assert_eq!( count, rcs.len() ); } } weak-table-0.3.2/src/ptr_weak_weak_hash_map.rs000064400000000000000000000251060072674642500175160ustar 00000000000000//! A hash map where the keys and values are both held by weak pointers, and keys are compared by //! pointer. use crate::compat::*; use super::by_ptr::*; use super::traits::*; use super::weak_weak_hash_map as base; pub use super::PtrWeakWeakHashMap; pub use super::weak_weak_hash_map::{Entry, Iter, Keys, Values, Drain, IntoIter}; 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)) } } impl PtrWeakWeakHashMap where K::Strong: Deref { /// Creates an empty `PtrWeakWeakHashMap` with the given capacity and hasher. /// /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> 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() } /// Is the map empty? /// /// 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.0.is_empty() } /// 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 { 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 _)) } /// 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, V::Strong) -> bool { self.0.retain(f) } /// Is this map a submap of the other, using the given value comparison. /// /// 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: &PtrWeakWeakHashMap, value_equal: F) -> bool where F: FnMut(V::Strong, V1::Strong) -> bool, V1: WeakElement, S1: BuildHasher { self.0.is_submap_with(&other.0, value_equal) } /// 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: &PtrWeakWeakHashMap) -> bool where V1: WeakElement, V::Strong: PartialEq, S1: BuildHasher { self.0.is_submap(&other.0) } /// 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: &PtrWeakWeakHashMap) -> bool where V1: WeakElement, S1: BuildHasher { self.0.domain_is_subset(&other.0) } } 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() } } impl PartialEq> for PtrWeakWeakHashMap where K: WeakElement, K::Strong: Deref, V: WeakElement, V1: WeakElement, V::Strong: PartialEq, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &PtrWeakWeakHashMap) -> bool { self.0 == other.0 } } impl Eq for PtrWeakWeakHashMap where K::Strong: Deref, V::Strong: Eq { } impl Default for PtrWeakWeakHashMap where K::Strong: Deref { fn default() -> Self { PtrWeakWeakHashMap(base::WeakWeakHashMap::, V, S>::default()) } } impl FromIterator<(K::Strong, V::Strong)> for PtrWeakWeakHashMap where K: WeakElement, K::Strong: Deref, V: WeakElement, S: BuildHasher + Default { fn from_iter>(iter: T) -> Self { PtrWeakWeakHashMap(base::WeakWeakHashMap::, V, S>::from_iter(iter)) } } impl Extend<(K::Strong, V::Strong)> for PtrWeakWeakHashMap where K: WeakElement, K::Strong: Deref, V: WeakElement, S: BuildHasher { fn extend>(&mut self, iter: T) { self.0.extend(iter) } } impl Debug for PtrWeakWeakHashMap where K: WeakElement, K::Strong: Debug, V: WeakElement, V::Strong: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } impl IntoIterator for PtrWeakWeakHashMap { type Item = (K::Strong, V::Strong); 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() } } impl<'a, K: WeakElement, V: WeakElement, S> IntoIterator for &'a PtrWeakWeakHashMap { 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() } } #[cfg(test)] mod test { use crate::compat::{ eprintln, rc::{Rc, Weak}, Vec, }; use super::{Entry, PtrWeakWeakHashMap}; // fn show_me(weakmap: &PtrWeakWeakHashMap, Weak>) { // for (key, _) in weakmap { // eprint!(" {:2}", *key); // } // eprintln!(); // } // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060 #[test] fn insert_and_check() { let mut rcs: Vec<(Rc, Rc)> = Vec::new(); for i in 0 .. 200 { rcs.push((Rc::new(i), Rc::new(i as f32 + 0.1))); } let mut weakmap: PtrWeakWeakHashMap, Weak> = PtrWeakWeakHashMap::new(); for (key, value) in rcs.iter().cloned() { weakmap.insert(key, value); // show_me(&weakmap); } let mut count = 0; for (key, value) in &rcs { assert!(weakmap.contains_key(key)); match weakmap.entry(Rc::clone(key)) { Entry::Occupied(occ) => { assert_eq!( occ.get(), value ); count += 1; } Entry::Vacant(_) => { eprintln!("PointerWeakWeakHashMap: missing: {}", *key); } } } assert_eq!( count, rcs.len() ); } } weak-table-0.3.2/src/size_policy.rs000064400000000000000000000010040072674642500153530ustar 00000000000000/// No reason for this number as of now. pub const DEFAULT_INITIAL_CAPACITY: usize = 8; /// When the approximate load factor reaches `COLLECT_LOAD_FACTOR`, we remove /// all the expired pointers and then consider resizing. pub const COLLECT_LOAD_FACTOR: f32 = 0.9; /// If, after collection, the load factor is above `GROW_LOAD_FACTOR`, we grow. pub const GROW_LOAD_FACTOR: f32 = 0.75; /// If, after collection, the load factor is below `SHRINK_LOAD_FACTOR`, we shrink. pub const SHRINK_LOAD_FACTOR: f32 = 0.25; weak-table-0.3.2/src/traits.rs000064400000000000000000000110040072674642500143310ustar 00000000000000//! Traits for describing strong and weak pointers and their use as elements and keys. //! //! These traits provide mechanisms for converting between weak and strong pointers //! ([`WeakElement`](trait.WeakElement.html)) and for dereferencing strong pointers //! ([`WeakKey`](trait.WeakKey.html)). Implementations of these traits are provided for //! `std::rc::Weak` and `std::sync::Weak`. If you would like to use your own pointer type //! as a weak element, you need to implement `WeakElement` for your weak pointer type; to use it //! as a weak key, implement `WeakKey` as well. use crate::compat::*; /// Interface for elements that can be stored in weak hash tables. /// /// This trait applies to the weak version of a reference-counted pointer; it can be used to /// convert a weak pointer into a strong pointer and back. For example, the impl for /// `std::rc::Weak` defines the `Strong` associated type as `std::rc::Rc`. Then method /// `new` can be used to downgrade an `Rc` to a `Weak`, and method `view` can be used to /// upgrade a `Weak` into an `Rc`, if it's still alive. If we think of the weak pointer as /// what is stored, then the strong pointer is a temporary view of it. pub trait WeakElement { /// The type at which a weak element can be viewed. /// /// For example, for `std::rc::Weak`, this will be `std::rc::Rc`. type Strong; /// Constructs a weak pointer from a strong pointer. /// /// This is usually implemented by a `downgrade` method. fn new(view: &Self::Strong) -> Self; /// Acquires a strong pointer from a weak pointer. /// /// This is usually implemented by an `upgrade` method. fn view(&self) -> Option; /// Is the given weak element expired? /// /// The default implemention checks whether a strong pointer can be obtained via `view`. fn is_expired(&self) -> bool { self.view().is_none() } /// Clones a strong pointer. /// /// The default implementation uses `new` and `view`; you should override it. fn clone(view: &Self::Strong) -> Self::Strong where Self: Sized { Self::new(view).view().expect("WeakElement::clone") } } /// Interface for elements that can act as keys in weak hash tables. /// /// To use an element as a weak hash map key or weak hash set element), the hash table /// needs to be able to view the actual key values to hash and compare them. This trait /// provides the necessary mechanism. pub trait WeakKey : WeakElement { /// The underlying key type. /// /// For example, for `std::rc::Weak`, this will be `T`. type Key: ?Sized + Eq + Hash; /// Allows borrowing a view of the key, via a callback. /// /// Rather than returning a borrowed reference to the actual key, this method passes a /// reference to the key to a callback with an implicit higher-order lifetime bound. This is /// necessary to get the lifetimes right in cases where the key is not actually store in the /// strong pointer. fn with_key(view: &Self::Strong, f: F) -> R where F: FnOnce(&Self::Key) -> R; /// Hashes the key `view` into the given `Hasher`. fn hash(view: &Self::Strong, h: &mut H) { Self::with_key(view, |k| k.hash(h)); } /// Returns whether the key `view` equals the given `key`. fn equals(view: &Self::Strong, key: &Q) -> bool where Q: ?Sized + Eq, Self::Key: Borrow { Self::with_key(view, |k| k.borrow() == key) } } impl WeakElement for rc::Weak { type Strong = rc::Rc; fn new(view: &Self::Strong) -> Self { rc::Rc::::downgrade(view) } fn view(&self) -> Option { self.upgrade() } fn clone(view: &Self::Strong) -> Self::Strong { view.clone() } } impl WeakKey for rc::Weak { type Key = T; fn with_key(view: &Self::Strong, f: F) -> R where F: FnOnce(&Self::Key) -> R { f(view) } } impl WeakElement for sync::Weak { type Strong = sync::Arc; fn new(view: &Self::Strong) -> Self { sync::Arc::::downgrade(view) } fn view(&self) -> Option { self.upgrade() } fn clone(view: &Self::Strong) -> Self::Strong { view.clone() } } impl WeakKey for sync::Weak { type Key = T; fn with_key(view: &Self::Strong, f: F) -> R where F: FnOnce(&Self::Key) -> R { f(view) } } weak-table-0.3.2/src/util.rs000064400000000000000000000003430072674642500140040ustar 00000000000000use crate::compat::*; pub fn new_boxed_option_slice(size: usize) -> Box<[Option]> { let mut vector = Vec::with_capacity(size); for _ in 0 .. size { vector.push(None) } vector.into_boxed_slice() } weak-table-0.3.2/src/weak_hash_set.rs000064400000000000000000000203340072674642500156360ustar 00000000000000//! A hash set where the elements are held by weak pointers and compared by value. use crate::compat::*; use super::traits::*; use super::weak_key_hash_map as base; 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)) } } 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() } /// Is the set empty? /// /// 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() } /// 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() } // 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 { self.0.contains_key(key) } /// Gets a strong reference to the given key, if found. /// /// # Examples /// /// ``` /// use weak_table::WeakHashSet; /// use std::rc::{Rc, Weak}; /// use std::ops::Deref; /// /// let mut set: WeakHashSet> = WeakHashSet::new(); /// /// let a = Rc::new("a".to_owned()); /// set.insert(a.clone()); /// /// let also_a = set.get("a").unwrap(); /// /// 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 { self.0.get_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: &Q) -> bool where Q: ?Sized + Eq + Hash, T::Key: Borrow { self.0.remove(key).is_some() } /// 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 { self.0.retain(|k, _| f(k)) } /// 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 { self.0.domain_is_subset(&other.0) } } /// An iterator over the elements of a set. pub struct Iter<'a, T: 'a>(base::Keys<'a, T, ()>); impl<'a, T: WeakElement> Iterator for Iter<'a, T> { type Item = T::Strong; fn next(&mut self) -> Option { self.0.next() } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// An iterator over the elements of a set. pub struct IntoIter(base::IntoIter); impl Iterator for IntoIter { type Item = T::Strong; fn next(&mut self) -> Option { self.0.next().map(|pair| pair.0) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// A draining iterator over the elements of a set. pub struct Drain<'a, T: 'a>(base::Drain<'a, T, ()>); impl<'a, T: WeakElement> Iterator for Drain<'a, T> { type Item = T::Strong; fn next(&mut self) -> Option { self.0.next().map(|pair| pair.0) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } 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()) } } impl PartialEq> for WeakHashSet where T: WeakKey, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &WeakHashSet) -> bool { self.0 == other.0 } } impl Eq for WeakHashSet where T::Key: Eq { } impl Default for WeakHashSet { fn default() -> Self { WeakHashSet(base::WeakKeyHashMap::::default()) } } impl FromIterator for WeakHashSet where T: WeakKey, S: BuildHasher + Default { fn from_iter>(iter: I) -> Self { WeakHashSet(base::WeakKeyHashMap::::from_iter( iter.into_iter().map(|k| (k, ())))) } } impl Extend for WeakHashSet { fn extend>(&mut self, iter: I) { self.0.extend(iter.into_iter().map(|k| (k, ()))) } } impl Debug for WeakHashSet where T::Strong: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } 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()) } } 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()) } } weak-table-0.3.2/src/weak_key_hash_map.rs000064400000000000000000001016330072674642500164720ustar 00000000000000//! A hash map where the keys are held by weak pointers and compared by key value. use super::*; use super::size_policy::*; use super::traits::*; use super::util::*; pub use super::WeakKeyHashMap; /// Represents an entry in the table which may be occupied or vacant. pub enum Entry<'a, K: 'a + WeakKey, V: 'a> { Occupied(OccupiedEntry<'a, K, V>), Vacant(VacantEntry<'a, K, V>), } /// An occupied entry, which can be removed or viewed. pub struct OccupiedEntry<'a, K: 'a + WeakKey, V: 'a>(InnerEntry<'a, K, V>); /// A vacant entry, which can be inserted in or viewed. pub struct VacantEntry<'a, K: 'a + WeakKey, V: 'a>(InnerEntry<'a, K, V>); struct InnerEntry<'a, K: 'a + WeakKey, V: 'a> { map: &'a mut WeakKeyInnerMap, pos: usize, key: K::Strong, hash_code: HashCode, } /// An iterator over the keys and values of the weak hash map. #[derive(Clone, Debug)] pub struct Iter<'a, K: 'a, V: 'a> { base: slice::Iter<'a, Bucket>, size: usize, } impl<'a, K: WeakElement, V> Iterator for Iter<'a, K, V> { type Item = (K::Strong, &'a V); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((ref weak_ptr, ref value, _)) = *bucket { self.size -= 1; if let Some(strong_ptr) = weak_ptr.view() { return Some((strong_ptr, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } #[derive(Debug)] /// An iterator over the keys and mutable values of the weak hash map. pub struct IterMut<'a, K: 'a, V: 'a> { base: slice::IterMut<'a, Bucket>, size: usize, } impl<'a, K: WeakElement, V> Iterator for IterMut<'a, K, V> { type Item = (K::Strong, &'a mut V); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((ref weak_ptr, ref mut value, _)) = *bucket { self.size -= 1; if let Some(strong_ptr) = weak_ptr.view() { return Some((strong_ptr, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } /// An iterator over the keys of the weak hash map. #[derive(Clone, Debug)] pub struct Keys<'a, K: 'a, V: 'a>(Iter<'a, K, V>); impl<'a, K: WeakElement, V> Iterator for Keys<'a, K, V> { type Item = K::Strong; fn next(&mut self) -> Option { self.0.next().map(|(k, _)| k) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// An iterator over the values of the weak hash map. #[derive(Clone, Debug)] pub struct Values<'a, K: 'a, V: 'a>(Iter<'a, K, V>); impl<'a, K: WeakElement, V> Iterator for Values<'a, K, V> { type Item = &'a V; fn next(&mut self) -> Option { self.0.next().map(|(_, v)| v) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[derive(Debug)] /// An iterator over the mutable values of the weak hash map. pub struct ValuesMut<'a, K: 'a, V: 'a>(IterMut<'a, K, V>); impl<'a, K: WeakElement, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; fn next(&mut self) -> Option { self.0.next().map(|(_, v)| v) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[derive(Debug)] /// An iterator that consumes the values of a weak hash map, leaving it empty. pub struct Drain<'a, K: 'a, V: 'a> { base: slice::IterMut<'a, Bucket>, size: usize, } impl<'a, K: WeakElement, V> Iterator for Drain<'a, K, V> { type Item = (K::Strong, V); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((weak_ptr, value, _)) = bucket.take() { self.size -= 1; if let Some(strong_ptr) = weak_ptr.view() { return Some((strong_ptr, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } impl<'a, K, V> Drop for Drain<'a, K, V> { fn drop(&mut self) { for option in &mut self.base { *option = None; } } } /// An iterator that consumes the values of a weak hash map, leaving it empty. pub struct IntoIter { base: vec::IntoIter>, size: usize, } impl Iterator for IntoIter { type Item = (K::Strong, V); fn next(&mut self) -> Option { for (weak_ptr, value, _) in (&mut self.base).flatten() { self.size -= 1; if let Some(strong_ptr) = weak_ptr.view() { return Some((strong_ptr, value)); } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } 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()) } } 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, inner: WeakKeyInnerMap { buckets: new_boxed_option_slice(capacity), len: 0, } } } /// 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() } /// This has some preconditions. fn resize(&mut self, capacity: usize) { let old_buckets = mem::replace(&mut self.inner.buckets, new_boxed_option_slice(capacity)); let iter = IntoIter { base: old_buckets.into_vec().into_iter(), size: self.inner.len, }; self.inner.len = 0; for (key, value) in iter { self.entry_no_grow(key).or_insert(value); } } /// 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; self.resize(new_capacity); } /// Returns an over-approximation of the number of elements. /// /// *O*(1) time pub fn len(&self) -> usize { self.inner.len } /// Is the map empty? /// /// 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 } /// 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 } fn maybe_adjust_size(&mut self) { if self.load_factor() > COLLECT_LOAD_FACTOR { self.remove_expired(); let load_factor = self.load_factor(); let capacity = self.capacity(); if load_factor > GROW_LOAD_FACTOR { self.resize(max(1, capacity * 2)); } else if load_factor < SHRINK_LOAD_FACTOR && capacity > DEFAULT_INITIAL_CAPACITY { self.resize(max(1, capacity / 2)); } } } /// 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) } fn entry_no_grow(&mut self, key: K::Strong) -> Entry { let mut inner = { let hash_code = self.hash(&key, K::hash); InnerEntry { pos: self.which_bucket(hash_code), map: &mut self.inner, hash_code, key, } }; for dist in 0 .. inner.capacity() { match inner.bucket_status() { BucketStatus::Unoccupied => return Entry::Vacant(VacantEntry(inner)), BucketStatus::MatchesKey => return Entry::Occupied(OccupiedEntry(inner)), BucketStatus::ProbeDistance(bucket_distance) => { if bucket_distance < dist { return Entry::Vacant(VacantEntry(inner)) } else { inner.pos = inner.next_bucket(inner.pos); } } } } panic!("WeakKeyHashTable::entry: out of space"); } /// Removes all associations from the map. /// /// *O*(*n*) time pub fn clear(&mut self) { self.drain(); } fn find_bucket(&self, key: &Q) -> Option<(usize, K::Strong, HashCode)> where Q: ?Sized + Hash + Eq, K::Key: Borrow { if self.capacity() == 0 { return None; } let hash_code = self.hash(key, Q::hash); let mut pos = self.which_bucket(hash_code); for dist in 0 .. self.capacity() { if let Some((ref weak_key, _, bucket_hash_code)) = self.inner.buckets[pos] { if bucket_hash_code == hash_code { if let Some(bucket_key) = weak_key.view() { if K::equals(&bucket_key, key) { return Some((pos, bucket_key, bucket_hash_code)); } } } let bucket_dist = self.probe_distance(pos, self.which_bucket(bucket_hash_code)); if bucket_dist < dist { return None; } } else { return None; } pos = self.next_bucket(pos); } None } /// 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 { self.find_bucket(key).and_then(move |tup| self.inner.buckets[tup.0].as_ref().map(|bucket| &bucket.1)) } /// 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 { self.find_bucket(key).is_some() } /// 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 { self.find_bucket(key).map(|tup| tup.1) } /// 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 { self.find_bucket(key).and_then(move |tup| self.inner.buckets[tup.0].as_ref().map(|bucket| (tup.1, &bucket.1))) } /// 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 { self.find_bucket(key).and_then(move |tup| self.inner.buckets[tup.0].as_mut().map(|bucket| &mut bucket.1)) } /// 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 { self.find_bucket(key).and_then(move |tup| self.inner.buckets[tup.0].as_mut().map(|bucket| (tup.1, &mut bucket.1))) } /// 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) => { Some(occupied.insert(value)) }, Entry::Vacant(vacant) => { vacant.insert(value); None } } } /// 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 { self.find_bucket(key).map(|(pos, strong_key, hash_code)| { OccupiedEntry(InnerEntry { map: &mut self.inner, pos, key: strong_key, hash_code, }).remove() }) } /// 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 { for i in 0 .. self.capacity() { let remove = match self.inner.buckets[i] { None => false, Some(ref mut bucket) => match bucket.0.view() { None => true, Some(key) => !f(key, &mut bucket.1), } }; if remove { self.inner.remove_index(i); } } } /// Is this map a submap of the other under the given value comparison `cmp`? /// /// In particular, for every key `k` of `self`, /// /// - `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, S1: BuildHasher { for (key, value1) in self { if let Some(value2) = K::with_key(&key, |k| other.get(k)) { if !cmp(value1, value2) { return false; } } else { return false; } } true } /// 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 { self.is_submap_with(other, PartialEq::eq) } /// 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 { self.is_submap_with(other, |_, _| true) } fn hash(&self, key: Q, hash: H) -> HashCode where H: FnOnce(Q, &mut S::Hasher) { let hasher = &mut self.hash_builder.build_hasher(); hash(key, hasher); HashCode(hasher.finish()) } } impl PartialEq> for WeakKeyHashMap where K: WeakKey, V: PartialEq, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &WeakKeyHashMap) -> bool { self.is_submap(other) && other.domain_is_subset(self) } } impl Eq for WeakKeyHashMap { } impl Default for WeakKeyHashMap { fn default() -> Self { WeakKeyHashMap::with_hasher(Default::default()) } } impl<'a, K, V, S, Q> ops::Index<&'a Q> for WeakKeyHashMap where K: WeakKey, K::Key: Borrow, S: BuildHasher, Q: ?Sized + Eq + Hash { type Output = V; fn index(&self, index: &'a Q) -> &Self::Output { self.get(index).expect("Index::index: key not found") } } impl<'a, K, V, S, Q> ops::IndexMut<&'a Q> for WeakKeyHashMap where K: WeakKey, K::Key: Borrow, S: BuildHasher, Q: ?Sized + Eq + Hash { fn index_mut(&mut self, index: &'a Q) -> &mut Self::Output { self.get_mut(index).expect("IndexMut::index_mut: key not found") } } impl iter::FromIterator<(K::Strong, V)> for WeakKeyHashMap where K: WeakKey, S: BuildHasher + Default { fn from_iter>(iter: T) -> Self { let mut result = WeakKeyHashMap::with_hasher(Default::default()); result.extend(iter); result } } impl iter::Extend<(K::Strong, V)> for WeakKeyHashMap where K: WeakKey, S: BuildHasher { fn extend>(&mut self, iter: T) { for (key, value) in iter { self.insert(key, value); } } } impl<'a, K, V, S> iter::Extend<(&'a K::Strong, &'a V)> for WeakKeyHashMap where K: 'a + WeakKey, K::Strong: Clone, V: 'a + Clone, S: BuildHasher { fn extend>(&mut self, iter: T) { for (key, value) in iter { self.insert(key.clone(), value.clone()); } } } enum BucketStatus { Unoccupied, MatchesKey, ProbeDistance(usize), } impl<'a, K: WeakKey, V> InnerEntry<'a, K, V> { // Gets the status of the current bucket. fn bucket_status(&self) -> BucketStatus { match &self.map.buckets[self.pos] { Some(bucket) => { if bucket.2 == self.hash_code { if let Some(key) = bucket.0.view() { if K::with_key(&self.key, |k| K::equals(&key, k)) { return BucketStatus::MatchesKey; } } } let dist = self.probe_distance(self.pos, self.which_bucket(bucket.2)); BucketStatus::ProbeDistance(dist) }, None => BucketStatus::Unoccupied, } } } 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) } /// 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(), Entry::Vacant(vacant) => vacant.insert(default()), } } /// 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(), Entry::Vacant(ref vacant) => vacant.key(), } } } 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); (self.0.key, value) } /// 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); value } /// Removes the entry, returning the value. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(self) -> V { self.remove_entry().1 } } 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], Some((K::new(&self.0.key), value, self.0.hash_code))); if let Some(full_bucket) = old_bucket { let next_bucket = self.next_bucket(self.0.pos); self.0.map.steal(next_bucket, full_bucket); } self.0.map.len += 1; &mut self.0.map.buckets[self.0.pos].as_mut().unwrap().1 } } impl WeakKeyInnerMap { // Steals buckets starting at `pos`, replacing them with `bucket`. fn steal(&mut self, mut pos: usize, mut bucket: FullBucket) { let mut my_dist = self.probe_distance(pos, self.which_bucket(bucket.2)); while let Some(hash_code) = self.buckets[pos].as_ref().and_then( |bucket| if bucket.0.is_expired() {None} else {Some(bucket.2)}) { let victim_dist = self.probe_distance(pos, self.which_bucket(hash_code)); if my_dist > victim_dist { mem::swap(self.buckets[pos].as_mut().unwrap(), &mut bucket); my_dist = victim_dist; } pos = self.next_bucket(pos); my_dist += 1; } self.buckets[pos] = Some(bucket); } /// Removes the element at `dst`, shifting if necessary to preserve invariants. fn remove_index(&mut self, mut dst: usize) { let mut src = self.next_bucket(dst); // We are going to remove the buckets in the range [dst, src) loop { let hash_code_option = self.buckets[src].as_ref().map(|tup| tup.2); if let Some(hash_code) = hash_code_option { let goal_pos = self.which_bucket(hash_code); let dist = self.probe_distance(src, goal_pos); if dist == 0 { break; } if !self.buckets[src].as_ref().unwrap().0.is_expired() { if in_interval(dst, goal_pos, src) { self.erase_range(dst, goal_pos); self.buckets[goal_pos] = self.buckets[src].take(); dst = self.next_bucket(goal_pos); } else { self.buckets[dst] = self.buckets[src].take(); dst = self.next_bucket(dst); } } } else { break; } src = self.next_bucket(src); } self.erase_range(dst, src); } /// Erases the (presumably expired, but not empty) elements in [start, limit). fn erase_range(&mut self, mut start: usize, limit: usize) { while start != limit { self.buckets[start] = None; self.len -= 1; start = self.next_bucket(start); } } } // Is value in [start, limit) modulo capacity? fn in_interval(start: usize, value: usize, limit: usize) -> bool { if start <= limit { start <= value && value < limit } else { start <= value || value < limit } } // Helper trait for computing with indices modulo capacity. trait ModuloCapacity { fn capacity(&self) -> usize; fn probe_distance(&self, actual: usize, ideal: usize) -> usize { if actual >= ideal { actual - ideal } else { actual + self.capacity() - ideal } } fn next_bucket(&self, pos: usize) -> usize { assert_ne!( self.capacity(), 0 ); (pos + 1) % self.capacity() } fn which_bucket(&self, hash_code: HashCode) -> usize { assert_ne!( self.capacity(), 0 ); (hash_code.0 as usize) % self.capacity() } } impl ModuloCapacity for WeakKeyInnerMap { fn capacity(&self) -> usize { self.buckets.len() } } impl ModuloCapacity for WeakKeyHashMap { fn capacity(&self) -> usize { self.inner.capacity() } } impl<'a, K: WeakKey, V> ModuloCapacity for InnerEntry<'a, K, V> { fn capacity(&self) -> usize { self.map.capacity() } } impl<'a, K: WeakKey, V> ModuloCapacity for OccupiedEntry<'a, K, V> { fn capacity(&self) -> usize { self.0.capacity() } } impl<'a, K: WeakKey, V> ModuloCapacity for VacantEntry<'a, K, V> { fn capacity(&self) -> usize { self.0.capacity() } } impl Debug for WeakKeyInnerMap where K: WeakElement, K::Strong: Debug, V: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{{ ")?; for (i, bucket) in self.buckets.iter().enumerate() { if let Some((ref k, ref v, _)) = *bucket { write!(f, "[{}] {:?} => {:?}, ", i, k.view(), *v)?; } } write!(f, "}}") } } impl Debug for WeakKeyHashMap where K::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: WeakKey, V: Debug> Debug for Entry<'a, K, V> where K::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { Entry::Occupied(ref e) => e.fmt(f), Entry::Vacant(ref e) => e.fmt(f), } } } impl<'a, K: WeakKey, V: Debug> Debug for OccupiedEntry<'a, K, V> where K::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.0.fmt(f) } } impl<'a, K: WeakKey, V: Debug> Debug for VacantEntry<'a, K, V> where K::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.0.fmt(f) } } impl<'a, K: WeakKey, V: Debug> Debug for InnerEntry<'a, K, V> where K::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "InnerEntry {{ pos = {}, buckets = {:?} }}", self.pos, self.map) } } 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, base: self.inner.buckets.into_vec().into_iter(), } } } 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(), size: self.inner.len, } } } 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(), size: self.inner.len, } } } 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; Drain { base: self.inner.buckets.iter_mut(), size: old_len, } } } #[cfg(test)] mod test { use crate::compat::{ eprintln, rc::{Rc, Weak}, String, Vec, }; use super::{Entry, WeakKeyHashMap}; #[test] fn simple() { let mut map: WeakKeyHashMap, usize> = WeakKeyHashMap::new(); assert_eq!( map.len(), 0 ); assert!( !map.contains_key("five") ); let five: Rc = Rc::from(String::from("five")); map.insert(five.clone(), 5); assert_eq!( map.len(), 1 ); assert!( map.contains_key("five") ); drop(five); assert_eq!( map.len(), 1 ); assert!( !map.contains_key("five") ); map.remove_expired(); assert_eq!( map.len(), 0 ); assert!( !map.contains_key("five") ); } // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060 #[test] fn insert_and_check() { let mut rcs: Vec> = Vec::new(); for i in 0 .. 50 { rcs.push(Rc::new(i)); } let mut weakmap: WeakKeyHashMap, f32> = WeakKeyHashMap::new(); for key in rcs.iter().cloned() { let f = *key as f32 + 0.1; weakmap.insert(key, f); } let mut count = 0; for key in &rcs { assert_eq!(weakmap.get(key), Some(&(**key as f32 + 0.1))); match weakmap.entry(Rc::clone(key)) { Entry::Occupied(_) => count += 1, Entry::Vacant(_) => eprintln!("WeakKeyHashMap: missing: {}", *key), } } assert_eq!( count, rcs.len() ); } } weak-table-0.3.2/src/weak_value_hash_map.rs000064400000000000000000000661330072674642500170230ustar 00000000000000//! A hash map where the values are held by weak pointers. use super::*; use super::size_policy::*; use super::traits::*; use super::util::*; pub use super::WeakValueHashMap; /// Represents an entry in the table which may be occupied or vacant. pub enum Entry<'a, K: 'a, V: 'a + WeakElement> { Occupied(OccupiedEntry<'a, K, V>), Vacant(VacantEntry<'a, K, V>), } /// An occupied entry, which can be removed or viewed. pub struct OccupiedEntry<'a, K: 'a, V: 'a + WeakElement> { inner: InnerEntry<'a, K, V>, value: V::Strong, } /// A vacant entry, which can be inserted in or viewed. pub struct VacantEntry<'a, K: 'a, V: 'a + WeakElement> { inner: InnerEntry<'a, K, V>, } struct InnerEntry<'a, K: 'a, V: 'a + WeakElement> { map: &'a mut WeakValueInnerMap, pos: usize, key: K, hash_code: HashCode, } /// An iterator over the keys and values of the weak hash map. #[derive(Clone, Debug)] pub struct Iter<'a, K: 'a, V: 'a> { base: slice::Iter<'a, Bucket>, size: usize, } impl<'a, K, V: WeakElement> Iterator for Iter<'a, K, V> { type Item = (&'a K, V::Strong); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((ref key, ref weak_value, _)) = *bucket { self.size -= 1; if let Some(value) = weak_value.view() { return Some((key, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } /// An iterator over the keys of the weak hash map. #[derive(Clone, Debug)] pub struct Keys<'a, K: 'a, V: 'a>(Iter<'a, K, V>); impl<'a, K, V: WeakElement> Iterator for Keys<'a, K, V> { type Item = &'a K; fn next(&mut self) -> Option { self.0.next().map(|(k, _)| k) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// An iterator over the values of the weak hash map. #[derive(Clone, Debug)] pub struct Values<'a, K: 'a, V: 'a>(Iter<'a, K, V>); impl<'a, K, V: WeakElement> Iterator for Values<'a, K, V> { type Item = V::Strong; fn next(&mut self) -> Option { self.0.next().map(|(_, v)| v) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[derive(Debug)] /// An iterator that consumes the values of a weak hash map, leaving it empty. pub struct Drain<'a, K: 'a, V: 'a> { base: slice::IterMut<'a, Bucket>, size: usize, } impl<'a, K, V: WeakElement> Iterator for Drain<'a, K, V> { type Item = (K, V::Strong); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((key, weak_value, _)) = bucket.take() { self.size -= 1; if let Some(value) = weak_value.view() { return Some((key, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } impl<'a, K, V> Drop for Drain<'a, K, V> { fn drop(&mut self) { for option in &mut self.base { *option = None; } } } /// An iterator that consumes the values of a weak hash map, leaving it empty. pub struct IntoIter { base: vec::IntoIter>, size: usize, } impl Iterator for IntoIter { type Item = (K, V::Strong); fn next(&mut self) -> Option { for (key, weak_value, _) in (&mut self.base).flatten() { self.size -= 1; if let Some(value) = weak_value.view() { return Some((key, value)); } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } 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()) } } 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, inner: WeakValueInnerMap { buckets: new_boxed_option_slice(capacity), len: 0, } } } /// 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() } /// This has some preconditions. fn resize(&mut self, capacity: usize) { let old_buckets = mem::replace(&mut self.inner.buckets, new_boxed_option_slice(capacity)); let iter = IntoIter { base: old_buckets.into_vec().into_iter(), size: self.inner.len, }; self.inner.len = 0; for (key, value) in iter { self.entry_no_grow(key).or_insert(value); } } /// 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; self.resize(new_capacity); } /// Returns an over-approximation of the number of elements. /// /// *O*(1) time pub fn len(&self) -> usize { self.inner.len } /// Is the map empty? /// /// 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 } /// 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 } fn maybe_adjust_size(&mut self) { if self.load_factor() > COLLECT_LOAD_FACTOR { self.remove_expired(); let load_factor = self.load_factor(); let capacity = self.capacity(); if load_factor > GROW_LOAD_FACTOR { self.resize(max(1, capacity * 2)); } else if load_factor < SHRINK_LOAD_FACTOR && capacity > DEFAULT_INITIAL_CAPACITY { self.resize(max(1, capacity / 2)); } } } /// 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) } fn entry_no_grow(&mut self, key: K) -> Entry { let mut inner = { let hash_code = self.hash(&key); InnerEntry { pos: self.which_bucket(hash_code), map: &mut self.inner, hash_code, key, } }; for dist in 0 .. inner.capacity() { match inner.bucket_status() { BucketStatus::Unoccupied => return Entry::Vacant(VacantEntry {inner}), BucketStatus::MatchesKey(value) => { return Entry::Occupied(OccupiedEntry {inner, value}) } BucketStatus::ProbeDistance(bucket_distance) => { if bucket_distance < dist { return Entry::Vacant(VacantEntry {inner}) } else { inner.pos = inner.next_bucket(inner.pos); } } } } panic!("WeakValueHashTable::entry: out of space"); } /// Removes all associations from the map. /// /// *O*(*n*) time pub fn clear(&mut self) { self.drain(); } fn find_bucket(&self, key: &Q) -> Option<(usize, V::Strong)> where Q: ?Sized + Hash + Eq, K: Borrow { if self.capacity() == 0 { return None; } let hash_code = self.hash(key); let mut pos = self.which_bucket(hash_code); for dist in 0 .. self.capacity() { if let Some((ref bucket_key, ref weak_value, bucket_hash_code)) = self.inner.buckets[pos] { if bucket_hash_code == hash_code { if let Some(value) = weak_value.view() { if bucket_key.borrow() == key { return Some((pos, value)); } } } let bucket_dist = self.probe_distance(pos, self.which_bucket(hash_code)); if bucket_dist < dist { return None; } } else { return None; } pos = self.next_bucket(pos); } None } /// 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 { self.find_bucket(key).map(|tup| tup.1) } /// 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 { self.find_bucket(key).is_some() } /// 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) => { Some(occupied.insert(value)) }, Entry::Vacant(vacant) => { vacant.insert(value); None } } } /// 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 { if let Some((pos, value)) = self.find_bucket(key) { self.inner.remove_index(pos); Some(value) } else { None } } /// 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 { for i in 0 .. self.capacity() { let remove = match self.inner.buckets[i] { None => false, Some(ref mut bucket) => match bucket.1.view() { None => true, Some(value) => !f(&bucket.0, value), } }; if remove { self.inner.remove_index(i); } } } /// Is this map a submap of the other, using the given value comparison. /// /// 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, F: FnMut(V::Strong, V1::Strong) -> bool, S1: BuildHasher { for (key, value1) in self { if let Some(value2) = other.get(key) { if !value_equal(value1, value2) { return false; } } else { return false; } } true } /// 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, S1: BuildHasher { self.is_submap_with(other, |v, v1| v == v1) } /// 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 { self.is_submap_with(other, |_, _| true) } fn hash(&self, key: &Q) -> HashCode where Q: ?Sized + Hash, K: Borrow { let mut hasher = self.hash_builder.build_hasher(); key.hash(&mut hasher); HashCode(hasher.finish()) } } impl PartialEq> for WeakValueHashMap where K: Eq + Hash, V: WeakElement, V1: WeakElement, V::Strong: PartialEq, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &WeakValueHashMap) -> bool { self.is_submap(other) && other.domain_is_subset(self) } } impl Eq for WeakValueHashMap where V::Strong: Eq { } impl Default for WeakValueHashMap { fn default() -> Self { WeakValueHashMap::with_hasher(Default::default()) } } impl iter::FromIterator<(K, V::Strong)> for WeakValueHashMap where K: Eq + Hash, V: WeakElement, S: BuildHasher + Default { fn from_iter>(iter: T) -> Self { let mut result = WeakValueHashMap::with_hasher(Default::default()); result.extend(iter); result } } impl Extend<(K, V::Strong)> for WeakValueHashMap where K: Eq + Hash, V: WeakElement, S: BuildHasher { fn extend>(&mut self, iter: T) { for (key, value) in iter { self.insert(key, value); } } } impl<'a, K, V, S> Extend<(&'a K, &'a V::Strong)> for WeakValueHashMap where K: 'a + Eq + Hash + Clone, V: 'a + WeakElement, V::Strong: Clone, S: BuildHasher { fn extend>(&mut self, iter: T) { for (key, value) in iter { self.insert(key.clone(), value.clone()); } } } enum BucketStatus { Unoccupied, MatchesKey(V::Strong), ProbeDistance(usize), } impl<'a, K: Eq + Hash, V: WeakElement> InnerEntry<'a, K, V> { // Gets the status of the current bucket. fn bucket_status(&self) -> BucketStatus { match &self.map.buckets[self.pos] { Some(bucket) => { if bucket.2 == self.hash_code { if let Some(value) = bucket.1.view() { if self.key == bucket.0 { return BucketStatus::MatchesKey(value); } } } let dist = self.probe_distance(self.pos, self.which_bucket(bucket.2)); BucketStatus::ProbeDistance(dist) }, None => BucketStatus::Unoccupied, } } } 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(), Entry::Vacant(vacant) => vacant.insert(default()), } } /// Returns a reference to this entry's key. /// /// *O*(1) time pub fn key(&self) -> &K { match *self { Entry::Occupied(ref occupied) => occupied.key(), Entry::Vacant(ref vacant) => vacant.key(), } } } 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(); self.inner.map.remove_index(self.inner.pos); (key, value) } /// 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 } } 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; let old_bucket = mem::replace( &mut map.buckets[pos], Some((key, V::new(&value), hash_code))); if let Some(full_bucket) = old_bucket { let next_bucket = map.next_bucket(pos); map.steal(next_bucket, full_bucket); } map.len += 1; value } } impl WeakValueInnerMap { // Steals buckets starting at `pos`, replacing them with `bucket`. fn steal(&mut self, mut pos: usize, mut bucket: FullBucket) { let mut my_dist = self.probe_distance(pos, self.which_bucket(bucket.2)); while let Some(hash_code) = self.buckets[pos].as_ref().and_then( |bucket| if bucket.1.is_expired() {None} else {Some(bucket.2)}) { let victim_dist = self.probe_distance(pos, self.which_bucket(hash_code)); if my_dist > victim_dist { mem::swap(self.buckets[pos].as_mut().unwrap(), &mut bucket); my_dist = victim_dist; } pos = self.next_bucket(pos); my_dist += 1; } self.buckets[pos] = Some(bucket); } /// Removes the element at `dst`, shifting if necessary to preserve invariants. fn remove_index(&mut self, mut dst: usize) { let mut src = self.next_bucket(dst); // We are going to remove the buckets in the range [dst, src) loop { let hash_code_option = self.buckets[src].as_ref().map(|tup| tup.2); if let Some(hash_code) = hash_code_option { let goal_pos = self.which_bucket(hash_code); let dist = self.probe_distance(src, goal_pos); if dist == 0 { break; } if !self.buckets[src].as_ref().unwrap().1.is_expired() { if in_interval(dst, goal_pos, src) { self.erase_range(dst, goal_pos); self.buckets[goal_pos] = self.buckets[src].take(); dst = self.next_bucket(goal_pos); } else { self.buckets[dst] = self.buckets[src].take(); dst = self.next_bucket(dst); } } } else { break; } src = self.next_bucket(src); } self.erase_range(dst, src); } /// Erases the (presumably expired, but not empty) elements in [start, limit). fn erase_range(&mut self, mut start: usize, limit: usize) { while start != limit { self.buckets[start] = None; self.len -= 1; start = self.next_bucket(start); } } } // Is value in [start, limit) modulo capacity? fn in_interval(start: usize, value: usize, limit: usize) -> bool { if start <= limit { start <= value && value < limit } else { start <= value || value < limit } } // Helper trait for computing with indices modulo capacity. trait ModuloCapacity { fn capacity(&self) -> usize; fn probe_distance(&self, actual: usize, ideal: usize) -> usize { if actual >= ideal { actual - ideal } else { actual + self.capacity() - ideal } } fn next_bucket(&self, pos: usize) -> usize { assert_ne!( self.capacity(), 0 ); (pos + 1) % self.capacity() } fn which_bucket(&self, hash_code: HashCode) -> usize { assert_ne!( self.capacity(), 0 ); (hash_code.0 as usize) % self.capacity() } } impl ModuloCapacity for WeakValueInnerMap { fn capacity(&self) -> usize { self.buckets.len() } } impl ModuloCapacity for WeakValueHashMap { fn capacity(&self) -> usize { self.inner.capacity() } } impl<'a, K, V: WeakElement> ModuloCapacity for InnerEntry<'a, K, V> { fn capacity(&self) -> usize { self.map.capacity() } } impl<'a, K, V: WeakElement> ModuloCapacity for OccupiedEntry<'a, K, V> { fn capacity(&self) -> usize { self.inner.capacity() } } impl<'a, K, V: WeakElement> ModuloCapacity for VacantEntry<'a, K, V> { fn capacity(&self) -> usize { self.inner.capacity() } } impl Debug for WeakValueInnerMap where K: Debug, V: WeakElement, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{{ ")?; for (i, bucket) in self.buckets.iter().enumerate() { if let Some((k, v, _)) = bucket { write!(f, "[{}] {:?} => {:?}, ", i, *k, v.view())?; } } write!(f, "}}") } } impl Debug for WeakValueHashMap where V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: Debug, V: WeakElement> Debug for Entry<'a, K, V> where V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { Entry::Occupied(ref e) => e.fmt(f), Entry::Vacant(ref e) => e.fmt(f), } } } impl<'a, K: Debug, V: WeakElement> Debug for OccupiedEntry<'a, K, V> where V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: Debug, V: WeakElement> Debug for VacantEntry<'a, K, V> where V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: Debug, V: WeakElement> Debug for InnerEntry<'a, K, V> where V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "InnerEntry {{ pos = {}, buckets = {:?} }}", self.pos, self.map) } } 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, base: self.inner.buckets.into_vec().into_iter(), } } } 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(), size: self.inner.len, } } } 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; Drain { base: self.inner.buckets.iter_mut(), size: old_len, } } } weak-table-0.3.2/src/weak_weak_hash_map.rs000064400000000000000000000711330072674642500166320ustar 00000000000000//! A hash map where the keys and values are both held by weak pointers, and keys are compared by //! value. use super::*; use super::size_policy::*; use super::traits::*; use super::util::*; pub use super::WeakWeakHashMap; /// Represents an entry in the table which may be occupied or vacant. pub enum Entry<'a, K: 'a + WeakKey, V: 'a + WeakElement> { Occupied(OccupiedEntry<'a, K, V>), Vacant(VacantEntry<'a, K, V>), } /// An occupied entry, which can be removed or viewed. pub struct OccupiedEntry<'a, K: 'a + WeakKey, V: 'a + WeakElement> { inner: InnerEntry<'a, K, V>, value: V::Strong, } /// A vacant entry, which can be inserted in or viewed. pub struct VacantEntry<'a, K: 'a + WeakKey, V: 'a + WeakElement> { inner: InnerEntry<'a, K, V>, } struct InnerEntry<'a, K: 'a + WeakKey, V: 'a> { map: &'a mut WeakWeakInnerMap, pos: usize, key: K::Strong, hash_code: HashCode, } /// An iterator over the keys and values of the weak hash map. #[derive(Clone, Debug)] pub struct Iter<'a, K: 'a, V: 'a> { base: slice::Iter<'a, Bucket>, size: usize, } impl<'a, K: WeakElement, V: WeakElement> Iterator for Iter<'a, K, V> { type Item = (K::Strong, V::Strong); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((ref weak_key, ref weak_value, _)) = *bucket { self.size -= 1; if let (Some(key), Some(value)) = (weak_key.view(), weak_value.view()) { return Some((key, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } /// An iterator over the keys of the weak hash map. #[derive(Clone, Debug)] pub struct Keys<'a, K: 'a, V: 'a>(Iter<'a, K, V>); impl<'a, K: WeakElement, V: WeakElement> Iterator for Keys<'a, K, V> { type Item = K::Strong; fn next(&mut self) -> Option { self.0.next().map(|(k, _)| k) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } /// An iterator over the values of the weak hash map. #[derive(Clone, Debug)] pub struct Values<'a, K: 'a, V: 'a>(Iter<'a, K, V>); impl<'a, K: WeakElement, V: WeakElement> Iterator for Values<'a, K, V> { type Item = V::Strong; fn next(&mut self) -> Option { self.0.next().map(|(_, v)| v) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[derive(Debug)] /// An iterator that consumes the values of a weak hash map, leaving it empty. pub struct Drain<'a, K: 'a, V: 'a> { base: slice::IterMut<'a, Bucket>, size: usize, } impl<'a, K: WeakElement, V: WeakElement> Iterator for Drain<'a, K, V> { type Item = (K::Strong, V::Strong); fn next(&mut self) -> Option { for bucket in &mut self.base { if let Some((weak_key, weak_value, _)) = bucket.take() { self.size -= 1; if let (Some(key), Some(value)) = (weak_key.view(), weak_value.view()) { return Some((key, value)); } } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } impl<'a, K, V> Drop for Drain<'a, K, V> { fn drop(&mut self) { for option in &mut self.base { *option = None; } } } /// An iterator that consumes the values of a weak hash map, leaving it empty. pub struct IntoIter { base: vec::IntoIter>, size: usize, } impl Iterator for IntoIter { type Item = (K::Strong, V::Strong); fn next(&mut self) -> Option { for (weak_key, weak_value, _) in (&mut self.base).flatten() { self.size -= 1; if let (Some(key), Some(value)) = (weak_key.view(), weak_value.view()) { return Some((key, value)); } } None } fn size_hint(&self) -> (usize, Option) { (0, Some(self.size)) } } 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()) } } 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, inner: WeakWeakInnerMap { buckets: new_boxed_option_slice(capacity), len: 0, } } } /// 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() } /// This has some preconditions. fn resize(&mut self, capacity: usize) { let old_buckets = mem::replace(&mut self.inner.buckets, new_boxed_option_slice(capacity)); let iter = IntoIter { base: old_buckets.into_vec().into_iter(), size: self.inner.len, }; self.inner.len = 0; for (key, value) in iter { self.entry_no_grow(key).or_insert(value); } } /// 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; self.resize(new_capacity); } /// Returns an over-approximation of the number of elements. /// /// *O*(1) time pub fn len(&self) -> usize { self.inner.len } /// Is the map empty? /// /// 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 } /// 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 } fn maybe_adjust_size(&mut self) { if self.load_factor() > COLLECT_LOAD_FACTOR { self.remove_expired(); let load_factor = self.load_factor(); let capacity = self.capacity(); if load_factor > GROW_LOAD_FACTOR { self.resize(max(1, capacity * 2)); } else if load_factor < SHRINK_LOAD_FACTOR && capacity > DEFAULT_INITIAL_CAPACITY { self.resize(max(1, capacity / 2)); } } } /// 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) } fn entry_no_grow(&mut self, key: K::Strong) -> Entry { let mut inner = { let hash_code = self.hash(&key, K::hash); InnerEntry { pos: self.which_bucket(hash_code), map: &mut self.inner, hash_code, key, } }; for dist in 0 .. inner.capacity() { match inner.bucket_status() { BucketStatus::Unoccupied => return Entry::Vacant(VacantEntry {inner}), BucketStatus::MatchesKey(value) => return Entry::Occupied(OccupiedEntry {value, inner}), BucketStatus::ProbeDistance(bucket_distance) => { if bucket_distance < dist { return Entry::Vacant(VacantEntry {inner}) } else { inner.pos = inner.next_bucket(inner.pos); } } } } panic!("WeakKeyHashTable::entry: out of space"); } /// Removes all associations from the map. /// /// *O*(*n*) time pub fn clear(&mut self) { self.drain(); } fn find_bucket(&self, key: &Q) -> Option<(usize, K::Strong, V::Strong)> where Q: ?Sized + Hash + Eq, K::Key: Borrow { if self.capacity() == 0 { return None; } let hash_code = self.hash(key, Q::hash); let mut pos = self.which_bucket(hash_code); for dist in 0 .. self.capacity() { if let Some((ref w_key, ref w_value, b_hash_code)) = self.inner.buckets[pos] { if b_hash_code == hash_code { if let (Some(b_key), Some(b_value)) = (w_key.view(), w_value.view()) { if K::equals(&b_key, key) { return Some((pos, b_key, b_value)); } } } let bucket_dist = self.probe_distance(pos, self.which_bucket(hash_code)); if bucket_dist < dist { return None; } } else { return None; } pos = self.next_bucket(pos); } None } /// 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 { self.find_bucket(key).map(|tup| tup.2) } /// 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 { self.find_bucket(key).map(|tup| tup.1) } /// 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 { self.find_bucket(key).map(|tup| (tup.1, tup.2)) } /// 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 { self.find_bucket(key).is_some() } /// 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) => { Some(occupied.insert(value)) }, Entry::Vacant(vacant) => { vacant.insert(value); None } } } /// 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 { if let Some((pos, _, value)) = self.find_bucket(key) { self.inner.remove_index(pos); Some(value) } else { None } } /// 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 { for i in 0 .. self.capacity() { let remove = match self.inner.buckets[i] { None => false, Some(ref bucket) => match (bucket.0.view(), bucket.1.view()) { (Some(key), Some(value)) => !f(key, value), _ => true, } }; if remove { self.inner.remove_index(i); } } } /// Is this map a submap of the other, using the given value comparison. /// /// 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, F: FnMut(V::Strong, V1::Strong) -> bool, S1: BuildHasher { for (key, value1) in self { if let Some(value2) = K::with_key(&key, |k| other.get(k)) { if !value_equal(value1, value2) { return false; } } else { return false; } } true } /// 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, S1: BuildHasher { self.is_submap_with(other, |v, v1| v == v1) } /// 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 { self.is_submap_with(other, |_, _| true) } fn hash(&self, key: Q, hash: H) -> HashCode where H: FnOnce(Q, &mut S::Hasher) { let hasher = &mut self.hash_builder.build_hasher(); hash(key, hasher); HashCode(hasher.finish()) } } impl PartialEq> for WeakWeakHashMap where K: WeakKey, V: WeakElement, V1: WeakElement, V::Strong: PartialEq, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &WeakWeakHashMap) -> bool { self.is_submap(other) && other.domain_is_subset(self) } } impl Eq for WeakWeakHashMap where V::Strong: Eq { } impl Default for WeakWeakHashMap { fn default() -> Self { WeakWeakHashMap::with_hasher(Default::default()) } } impl iter::FromIterator<(K::Strong, V::Strong)> for WeakWeakHashMap where K: WeakKey, V: WeakElement, S: BuildHasher + Default { fn from_iter>(iter: T) -> Self { let mut result = WeakWeakHashMap::with_hasher(Default::default()); result.extend(iter); result } } impl Extend<(K::Strong, V::Strong)> for WeakWeakHashMap where K: WeakKey, V: WeakElement, S: BuildHasher { fn extend>(&mut self, iter: T) { for (key, value) in iter { self.insert(key, value); } } } enum BucketStatus { Unoccupied, MatchesKey(V::Strong), ProbeDistance(usize), } impl<'a, K: WeakKey, V: WeakElement> InnerEntry<'a, K, V> { // Gets the status of the current bucket. fn bucket_status(&self) -> BucketStatus { match &self.map.buckets[self.pos] { Some(bucket) => { if bucket.2 == self.hash_code { if let (Some(key), Some(value)) = (bucket.0.view(), bucket.1.view()) { if K::with_key(&self.key, |k| K::equals(&key, k)) { return BucketStatus::MatchesKey(value); } } } let dist = self.probe_distance(self.pos, self.which_bucket(bucket.2)); BucketStatus::ProbeDistance(dist) }, None => BucketStatus::Unoccupied, } } } 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) } /// 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(), Entry::Vacant(vacant) => vacant.insert(default()), } } /// 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(), Entry::Vacant(ref vacant) => vacant.key(), } } } 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(); self.inner.map.remove_index(self.inner.pos); (self.inner.key, value) } /// 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 } } 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], Some((K::new(&self.inner.key), V::new(&value), self.inner.hash_code))); if let Some(full_bucket) = old_bucket { let next_bucket = self.next_bucket(self.inner.pos); self.inner.map.steal(next_bucket, full_bucket); } self.inner.map.len += 1; value } } impl WeakWeakInnerMap { // Steals buckets starting at `pos`, replacing them with `bucket`. fn steal(&mut self, mut pos: usize, mut bucket: FullBucket) { let mut my_dist = self.probe_distance(pos, self.which_bucket(bucket.2)); while let Some(hash_code) = self.buckets[pos].as_ref().and_then( |bucket| if bucket.0.is_expired() || bucket.1.is_expired() { None } else { Some(bucket.2) }) { let victim_dist = self.probe_distance(pos, self.which_bucket(hash_code)); if my_dist > victim_dist { mem::swap(self.buckets[pos].as_mut().unwrap(), &mut bucket); my_dist = victim_dist; } pos = self.next_bucket(pos); my_dist += 1; } self.buckets[pos] = Some(bucket); } /// Removes the element at `dst`, shifting if necessary to preserve invariants. fn remove_index(&mut self, mut dst: usize) { let mut src = self.next_bucket(dst); // We are going to remove the buckets in the range [dst, src) loop { let hash_code_option = self.buckets[src].as_ref().map(|tup| tup.2); if let Some(hash_code) = hash_code_option { let goal_pos = self.which_bucket(hash_code); let dist = self.probe_distance(src, goal_pos); if dist == 0 { break; } let expired = { let bucket = self.buckets[src].as_ref().unwrap(); bucket.0.is_expired() || bucket.1.is_expired() }; if !expired { if in_interval(dst, goal_pos, src) { self.erase_range(dst, goal_pos); self.buckets[goal_pos] = self.buckets[src].take(); dst = self.next_bucket(goal_pos); } else { self.buckets[dst] = self.buckets[src].take(); dst = self.next_bucket(dst); } } } else { break; } src = self.next_bucket(src); } self.erase_range(dst, src); } /// Erases the (presumably expired, but not empty) elements in [start, limit). fn erase_range(&mut self, mut start: usize, limit: usize) { while start != limit { self.buckets[start] = None; self.len -= 1; start = self.next_bucket(start); } } } // Is value in [start, limit) modulo capacity? fn in_interval(start: usize, value: usize, limit: usize) -> bool { if start <= limit { start <= value && value < limit } else { start <= value || value < limit } } // Helper trait for computing with indices modulo capacity. trait ModuloCapacity { fn capacity(&self) -> usize; fn probe_distance(&self, actual: usize, ideal: usize) -> usize { if actual >= ideal { actual - ideal } else { actual + self.capacity() - ideal } } fn next_bucket(&self, pos: usize) -> usize { assert_ne!( self.capacity(), 0 ); (pos + 1) % self.capacity() } fn which_bucket(&self, hash_code: HashCode) -> usize { assert_ne!( self.capacity(), 0 ); (hash_code.0 as usize) % self.capacity() } } impl ModuloCapacity for WeakWeakInnerMap { fn capacity(&self) -> usize { self.buckets.len() } } impl ModuloCapacity for WeakWeakHashMap { fn capacity(&self) -> usize { self.inner.capacity() } } impl<'a, K: WeakKey, V: WeakElement> ModuloCapacity for InnerEntry<'a, K, V> { fn capacity(&self) -> usize { self.map.capacity() } } impl<'a, K: WeakKey, V: WeakElement> ModuloCapacity for OccupiedEntry<'a, K, V> { fn capacity(&self) -> usize { self.inner.capacity() } } impl<'a, K: WeakKey, V: WeakElement> ModuloCapacity for VacantEntry<'a, K, V> { fn capacity(&self) -> usize { self.inner.capacity() } } impl Debug for WeakWeakInnerMap where K: WeakElement, K::Strong: Debug, V: WeakElement, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{{ ")?; for (i, bucket) in self.buckets.iter().enumerate() { if let Some((k, v, _)) = bucket { write!(f, "[{}] {:?} => {:?}, ", i, k.view(), v.view())?; } } write!(f, "}}") } } impl Debug for WeakWeakHashMap where K::Strong: Debug, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: WeakKey, V: WeakElement> Debug for Entry<'a, K, V> where K::Strong: Debug, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { Entry::Occupied(ref e) => e.fmt(f), Entry::Vacant(ref e) => e.fmt(f), } } } impl<'a, K: WeakKey, V: WeakElement> Debug for OccupiedEntry<'a, K, V> where K::Strong: Debug, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: WeakKey, V: WeakElement> Debug for VacantEntry<'a, K, V> where K::Strong: Debug, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.inner.fmt(f) } } impl<'a, K: WeakKey, V: WeakElement> Debug for InnerEntry<'a, K, V> where K::Strong: Debug, V::Strong: Debug { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "InnerEntry {{ pos = {}, buckets = {:?} }}", self.pos, self.map) } } impl IntoIterator for WeakWeakHashMap { type Item = (K::Strong, 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, base: self.inner.buckets.into_vec().into_iter(), } } } 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(), size: self.inner.len, } } } 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; Drain { base: self.inner.buckets.iter_mut(), size: old_len, } } } weak-table-0.3.2/tests/symbols.rs000064400000000000000000000017750072674642500151040ustar 00000000000000extern crate weak_table; use weak_table::WeakHashSet; use std::ops::Deref; use std::rc::{Rc, Weak}; #[derive(Clone, Debug)] pub struct Symbol(Rc); impl PartialEq for Symbol { fn eq(&self, other: &Symbol) -> bool { Rc::ptr_eq(&self.0, &other.0) } } impl Eq for Symbol {} impl Deref for Symbol { type Target = str; fn deref(&self) -> &str { &self.0 } } #[derive(Debug, Default)] pub struct SymbolTable(WeakHashSet>); impl SymbolTable { pub fn new() -> Self { Self::default() } pub fn intern(&mut self, name: &str) -> Symbol { if let Some(rc) = self.0.get(name) { Symbol(rc) } else { let rc = Rc::::from(name); self.0.insert(Rc::clone(&rc)); Symbol(rc) } } } #[test] fn interning() { let mut tab = SymbolTable::new(); let a0 = tab.intern("a"); let a1 = tab.intern("a"); let b = tab.intern("b"); assert_eq!(a0, a1); assert_ne!(a0, b); } weak-table-0.3.2/tests/weak_key_hash_map.rs000064400000000000000000000105410072674642500170420ustar 00000000000000use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hash; use std::rc::{Rc, Weak}; use quickcheck::{Arbitrary, Gen, quickcheck}; use weak_table::WeakKeyHashMap; use self::Cmd::*; fn test_script(script: &Script) -> bool where K: Clone + Debug + Eq + Hash, V: Clone + Debug + Eq { let mut tester = Tester::with_capacity(4); tester.execute_script(script); tester.check() } quickcheck! { fn prop_u8_u8(script: Script) -> bool { test_script(&script) } fn prop_string_usize(script: Script) -> bool { test_script(&script) } } #[derive(Clone, Debug)] pub enum Cmd { Insert(K, V), Reinsert(usize, V), RemoveInserted(usize), RemoveOther(K), ForgetInserted(usize), } #[derive(Clone, Debug)] pub struct Script(Vec>); #[derive(Clone, Debug)] pub struct Tester { weak: WeakKeyHashMap, V>, strong: HashMap, V>, log: Vec, } impl Tester where K: Hash + Eq + Clone + Debug, V: Eq + Clone + Debug { pub fn new() -> Self { Tester::with_capacity(8) } pub fn with_capacity(capacity: usize) -> Self { Tester { weak: WeakKeyHashMap::with_capacity(capacity), strong: HashMap::new(), log: Vec::new(), } } pub fn check(&self) -> bool { let copy = self.weak.iter().map(|(k, v)| (k, v.clone())).collect(); if self.strong == copy { // eprintln!("Tester::check: succeeded: {:?}", self.weak); true } else { eprintln!("Tester::check: failed: {:?} ≠ {:?}", self.strong, copy); false } } pub fn execute_script(&mut self, script: &Script) { // eprintln!("\n*** Starting script ***"); for cmd in &script.0 { self.execute_command(cmd); } } pub fn execute_command(&mut self, cmd: &Cmd) { // eprintln!("Executing command: {:?}", cmd); match *cmd { Insert(ref k, ref v) => self.insert(k, v, true), Reinsert(index, ref v) => self.reinsert(index, v), RemoveInserted(index) => self.remove_inserted(index), RemoveOther(ref k) => self.remove_other(k), ForgetInserted(index) => self.forget_inserted(index), } // eprintln!("Table state: {:?}", self.weak); } pub fn insert(&mut self, key: &K, value: &V, log: bool) { let key_ptr = Rc::new(key.clone()); self.weak.insert(key_ptr.clone(), value.clone()); self.strong.remove(key); self.strong.insert(key_ptr, value.clone()); if log { self.log.push(key.clone()); } } pub fn reinsert(&mut self, index: usize, value: &V) { if let Some(key) = self.nth_key_mod_len(index) { self.insert(&key, value, false); } } pub fn remove_inserted(&mut self, index: usize) { if let Some(key) = self.nth_key_mod_len(index) { self.strong.remove(&key); self.weak.remove(&key); } } pub fn remove_other(&mut self, key: &K) { self.strong.remove(key); self.weak.remove(key); } pub fn forget_inserted(&mut self, index: usize) { if let Some(key) = self.nth_key_mod_len(index) { self.strong.remove(&key); } } fn nth_key_mod_len(&self, n: usize) -> Option { if self.log.is_empty() { None } else { Some(self.log[n % self.log.len()].clone()) } } } impl Arbitrary for Cmd { fn arbitrary(g: &mut Gen) -> Self { let choice = u8::arbitrary(g); match choice % 10 { 0..=3 => Insert(K::arbitrary(g), V::arbitrary(g)), 4 => Reinsert(usize::arbitrary(g), V::arbitrary(g)), 5..=6 => RemoveInserted(usize::arbitrary(g)), 7 => RemoveOther(K::arbitrary(g)), 8..=9 => ForgetInserted(usize::arbitrary(g)), _ => unreachable!(), } } } impl Arbitrary for Script { fn arbitrary(g: &mut Gen) -> Self { Script(Vec::>::arbitrary(g)) } fn shrink(&self) -> Box> { Box::new(self.0.shrink().map(|v| Script(v))) } }