├── .circleci └── config.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src ├── lib.rs ├── linked_hash_map.rs ├── linked_hash_set.rs ├── lru_cache.rs └── serde.rs └── tests ├── linked_hash_map.rs ├── linked_hash_set.rs ├── lru_cache.rs └── serde.rs /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | docker: 6 | - image: cimg/rust:1.65.0 7 | steps: 8 | - checkout 9 | - run: 10 | name: Setup Rust 11 | command: | 12 | rustup toolchain uninstall nightly 13 | rustup toolchain install nightly -c miri rust-src rustfmt 14 | - run: 15 | name: Version information 16 | command: | 17 | rustc --version 18 | cargo --version 19 | rustc +nightly --version 20 | cargo +nightly --version 21 | rustup --version 22 | - run: 23 | name: Calculate dependencies 24 | command: cargo generate-lockfile 25 | - restore_cache: 26 | keys: 27 | - cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }} 28 | - run: 29 | name: Check Formatting 30 | command: | 31 | rustfmt --version 32 | cargo fmt --all -- --check --color=auto 33 | - run: 34 | name: Build all targets 35 | command: cargo build --all --all-targets 36 | - run: 37 | name: Run all tests 38 | command: cargo test --all --all-features 39 | - run: 40 | name: Run all tests under miri 41 | command: | 42 | cargo +nightly miri test --all-features 43 | - run: 44 | name: Run all tests under sanitizers 45 | command: | 46 | RUSTFLAGS="-Z sanitizer=address" cargo +nightly -Z build-std test --target x86_64-unknown-linux-gnu --all-features 47 | RUSTFLAGS="-Z sanitizer=leak" cargo +nightly test -Z build-std --target x86_64-unknown-linux-gnu --all-features 48 | RUSTFLAGS="-Z sanitizer=memory" cargo +nightly test -Z build-std --target x86_64-unknown-linux-gnu --all-features 49 | - save_cache: 50 | paths: 51 | - /usr/local/cargo/registry 52 | - target/debug/.fingerprint 53 | - target/debug/build 54 | - target/debug/deps 55 | key: cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }} 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | .DS_Store 5 | .envrc 6 | .direnv 7 | shell.nix 8 | .dir-locals.el -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.10.0] 2 | - API incompatible change: upgrade `hashbrown` to 0.15 (thank you @djc!). 3 | - API incompatible change: we now wrap `DefaultHashBuilder` and `DefaultHasher` 4 | from `hashbrown` so that in the future upgrading `hashbrown` is not an API 5 | incompatible change (thank you @djc!). 6 | 7 | ## [0.9.1] 8 | - Bugfix: `LruCache::contains_key` should take `&self` and not move the entry as 9 | though it is accessed. 10 | - Add basic `CursorMut` API to `HashMap` (thanks @olebedev!) 11 | - Bump `hashbrown` dependency to depend on a version of `hashbrown` past a 12 | downstream `zerocopy` dependency. 13 | - Don't depend on default features of `hashbrown`, removes `allocator-api2` 14 | dependency. 15 | 16 | ## [0.9.0] 17 | - API incompatible change: Don't panic in `reserve` and `try_reserve` in cases 18 | where a rehash is needed. Previously would panic, adds the proper bounds on 19 | reserve methods to do a rehash (previously bounds were missing, and reserve 20 | would result in panics). (Thank you @cuviper!) 21 | 22 | ## [0.8.4] 23 | - Now builds with `#![no_std]`. 24 | 25 | ## [0.8.3] 26 | - bump hashbrown to 0.14 27 | 28 | ## [0.8.2] 29 | - bump hashbrown to 0.13 30 | 31 | ## [0.8.1] 32 | - Add `retain_with_order` methods, equivalent to `retain` but which iterate 33 | through the map in the proper linked list order 34 | 35 | ## [0.8.0] 36 | - API incompatible change: No longer re-export hashbrown types so that bumping 37 | hashbrown is no longer an API compatible change. 38 | - bump hashbrown to 0.12 39 | - Fix implementation of `shrink_to_fit` to not panic when called on non-empty 40 | containers. 41 | 42 | ## [0.7.0] 43 | - API incompatible change: depend on hashbrown 0.11, changes re-exported types. 44 | - Fix `LinkedHashSet::back` to take `&self` not `&mut self`. 45 | - API incompatible change: equality tests on `LinkedHashSet` are now *ordered*, 46 | similar to `LinkedHashMap`. 47 | - Make the serde `Deserialize` implementations on `LinkedHashMap` and 48 | `LinkedHashSet` generic on the `BuildHasher` type. 49 | - Add `to_back` and `to_front` methods for `LinkedHashMap` to control entry 50 | order. 51 | 52 | ## [0.6.0] 53 | - API incompatible change: depend on hashbrown 0.9, re-export renamed 54 | hashbrown::TryReserveError type. 55 | - Add a `Debug` impl to `LruCache` (thanks @thomcc!) 56 | - Adjust trait bounds for `LinkedHashMap::retain`, `LinkedHashSet::default` to 57 | be less strict (to match hashbrown) 58 | - Adjust trait bounds for all `Debug` impls to be less strict (to match 59 | hashbrown). 60 | - Adjust trait bounds for all `IntoIterator` impls to be less strict (to match 61 | hashbrown). 62 | - Adjust trait bounds for `LruCache::with_hasher`, `LruCache::capacity`, 63 | `LruCache::len`, `LruCache::is_empty`, `LruCache::clear`, `LruCache::iter`, 64 | `LruCache::iter_mut`, and `LruCache::drain` to be less strict 65 | - Add optional serde support for `LinkedHashMap` and `LinkedHashSet`. 66 | - Add `to_back` and `to_front` methods for LinkedHashSet to control entry order. 67 | 68 | ## [0.5.1] 69 | - Add `LinkedHashMap::remove_entry` and `LruCache::remove_entry` 70 | - Add `LruCache::new_unbounded` constructor that sets capacity to usize::MAX 71 | - Add `LruCache::get` method to go with `LruCache::get_mut` 72 | - Add `LruCache::peek` and `LruCache::peek_mut` to access the cache without 73 | moving the entry in the LRU list 74 | 75 | ## [0.5.0] 76 | - API incompatible change: depend on hashbrown 0.7 77 | 78 | ## [0.4.0] 79 | - API incompatible change: depend on hashbrown 0.6 80 | - Passes miri 81 | 82 | ## [0.3.0] 83 | - Add some *minimal* documentation for methods that change the internal ordering. 84 | - Decide on a pattern for methods that change the internal ordering: the word 85 | "insert" means that it will move an existing entry to the back. 86 | - Some methods have been renamed to conform to the above system. 87 | 88 | ## [0.2.1] 89 | - Fix variance for LinkedHashMap (now covariant where appropriate) 90 | - Add Debug impls to many more associated types 91 | - Add LinkedHashSet 92 | - Add `LinkedHashMap::retain` 93 | 94 | ## [0.2.0] 95 | - Move `linked_hash_map` into its own module 96 | - Add `LruCache` type ported from `lru-cache` crate into its own module 97 | - Add `LruCache` entry and raw-entry API 98 | - Add `linked_hash_map` `IntoIter` iterator that is different from `Drain` iterator 99 | - Make `Drain` iterator recycle freed linked list nodes 100 | 101 | ## [0.1.0] 102 | - Initial release 103 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hashlink" 3 | version = "0.10.0" 4 | authors = ["kyren "] 5 | edition = "2018" 6 | description = "HashMap-like containers that hold their key-value pairs in a user controllable order" 7 | repository = "https://github.com/kyren/hashlink" 8 | documentation = "https://docs.rs/hashlink" 9 | readme = "README.md" 10 | keywords = ["data-structures", "no_std"] 11 | license = "MIT OR Apache-2.0" 12 | rust-version = "1.65" 13 | 14 | [badges] 15 | circle-ci = { repository = "kyren/hashlink", branch = "master" } 16 | 17 | [features] 18 | serde_impl = ["serde"] 19 | 20 | [dependencies] 21 | hashbrown = { version = "0.15", default-features = false, features = ["default-hasher", "inline-more"] } 22 | serde = { version = "1.0", default-features = false, optional = true } 23 | 24 | [dev-dependencies] 25 | serde_test = "1.0" 26 | rustc-hash = "2" 27 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | This work is derived in part from the `linked-hash-map` crate, Copyright (c) 2 | 2015 The Rust Project Developers 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hashlink -- HashMap-like containers that hold their key-value pairs in a user controllable order 2 | 3 | [![Build Status](https://img.shields.io/circleci/project/github/kyren/hashlink.svg)](https://circleci.com/gh/kyren/hashlink) 4 | [![Latest Version](https://img.shields.io/crates/v/hashlink.svg)](https://crates.io/crates/hashlink) 5 | [![API Documentation](https://docs.rs/hashlink/badge.svg)](https://docs.rs/hashlink) 6 | 7 | This crate is a fork of 8 | [linked-hash-map](https://github.com/contain-rs/linked-hash-map) that builds on 9 | top of [hashbrown](https://github.com/rust-lang/hashbrown) to implement more up 10 | to date versions of `LinkedHashMap` `LinkedHashSet`, and `LruCache`. 11 | 12 | One important API change is that when a `LinkedHashMap` is used as a LRU cache, 13 | it allows you to easily retrieve an entry and move it to the back OR produce a 14 | new entry at the back without needlessly repeating key hashing and lookups: 15 | 16 | ``` rust 17 | let mut lru_cache = LinkedHashMap::new(); 18 | let key = "key".to_owned(); 19 | // Try to find my expensive to construct and hash key 20 | let _cached_val = match lru_cache.raw_entry_mut().from_key(&key) { 21 | RawEntryMut::Occupied(mut occupied) => { 22 | // Cache hit, move entry to the back. 23 | occupied.to_back(); 24 | occupied.into_mut() 25 | } 26 | RawEntryMut::Vacant(vacant) => { 27 | // Insert expensive to construct key and expensive to compute value, 28 | // automatically inserted at the back. 29 | vacant.insert(key.clone(), 42).1 30 | } 31 | }; 32 | ``` 33 | 34 | Or, a simpler way to do the same thing: 35 | 36 | ``` rust 37 | let mut lru_cache = LinkedHashMap::new(); 38 | let key = "key".to_owned(); 39 | let _cached_val = lru_cache 40 | .raw_entry_mut() 41 | .from_key(&key) 42 | .or_insert_with(|| (key.clone(), 42)); 43 | ``` 44 | 45 | This crate contains a decent amount of unsafe code from handling its internal 46 | linked list, and the unsafe code has diverged quite a lot from the original 47 | `linked-hash-map` implementation. It currently passes tests under miri and 48 | sanitizers, but it should probably still receive more review and testing, and 49 | check for test code coverage. 50 | 51 | ## Credit 52 | 53 | There is a huge amount of code in this crate that is copied verbatim from 54 | `linked-hash-map` and `hashbrown`, especially tests, associated types like 55 | iterators, and things like `Debug` impls. 56 | 57 | ## License 58 | 59 | This library is licensed the same as 60 | [linked-hash-map](https://github.com/contain-rs/linked-hash-map) and 61 | [hashbrown](https://github.com/rust-lang/hashbrown), it is licensed under either 62 | of: 63 | 64 | * MIT license [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT 65 | * Apache License 2.0 [LICENSE-APACHE](LICENSE-APACHE) or https://opensource.org/licenses/Apache-2.0 66 | 67 | at your option. 68 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | extern crate alloc; 3 | 4 | pub mod linked_hash_map; 5 | pub mod linked_hash_set; 6 | pub mod lru_cache; 7 | #[cfg(feature = "serde_impl")] 8 | pub mod serde; 9 | 10 | use core::hash::{BuildHasher, Hasher}; 11 | 12 | pub use linked_hash_map::LinkedHashMap; 13 | pub use linked_hash_set::LinkedHashSet; 14 | pub use lru_cache::LruCache; 15 | 16 | /// Default hash builder, matches hashbrown's default hasher. 17 | /// 18 | /// See [`DefaultHasher`] for more details. 19 | #[derive(Clone, Copy, Default, Debug)] 20 | pub struct DefaultHashBuilder(hashbrown::DefaultHashBuilder); 21 | 22 | impl BuildHasher for DefaultHashBuilder { 23 | type Hasher = DefaultHasher; 24 | 25 | #[inline] 26 | fn build_hasher(&self) -> Self::Hasher { 27 | DefaultHasher(self.0.build_hasher()) 28 | } 29 | } 30 | 31 | /// Default hasher, as selected by hashbrown. 32 | #[derive(Clone)] 33 | pub struct DefaultHasher(::Hasher); 34 | 35 | impl Hasher for DefaultHasher { 36 | #[inline] 37 | fn write(&mut self, bytes: &[u8]) { 38 | self.0.write(bytes) 39 | } 40 | 41 | #[inline] 42 | fn write_u8(&mut self, i: u8) { 43 | self.0.write_u8(i) 44 | } 45 | 46 | #[inline] 47 | fn write_u16(&mut self, i: u16) { 48 | self.0.write_u16(i) 49 | } 50 | 51 | #[inline] 52 | fn write_u32(&mut self, i: u32) { 53 | self.0.write_u32(i) 54 | } 55 | 56 | #[inline] 57 | fn write_u64(&mut self, i: u64) { 58 | self.0.write_u64(i) 59 | } 60 | 61 | #[inline] 62 | fn write_u128(&mut self, i: u128) { 63 | self.0.write_u128(i) 64 | } 65 | 66 | #[inline] 67 | fn write_usize(&mut self, i: usize) { 68 | self.0.write_usize(i) 69 | } 70 | 71 | #[inline] 72 | fn finish(&self) -> u64 { 73 | self.0.finish() 74 | } 75 | 76 | #[inline] 77 | fn write_i8(&mut self, i: i8) { 78 | self.0.write_i8(i) 79 | } 80 | 81 | #[inline] 82 | fn write_i16(&mut self, i: i16) { 83 | self.0.write_i16(i) 84 | } 85 | 86 | #[inline] 87 | fn write_i32(&mut self, i: i32) { 88 | self.0.write_i32(i) 89 | } 90 | 91 | #[inline] 92 | fn write_i64(&mut self, i: i64) { 93 | self.0.write_i64(i) 94 | } 95 | 96 | #[inline] 97 | fn write_i128(&mut self, i: i128) { 98 | self.0.write_i128(i) 99 | } 100 | 101 | #[inline] 102 | fn write_isize(&mut self, i: isize) { 103 | self.0.write_isize(i) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/linked_hash_map.rs: -------------------------------------------------------------------------------- 1 | use core::{ 2 | alloc::Layout, 3 | borrow::Borrow, 4 | cmp::Ordering, 5 | fmt, 6 | hash::{BuildHasher, Hash, Hasher}, 7 | iter::FromIterator, 8 | marker::PhantomData, 9 | mem::{self, MaybeUninit}, 10 | ops::{Index, IndexMut}, 11 | ptr::{self, NonNull}, 12 | }; 13 | 14 | use alloc::boxed::Box; 15 | use hashbrown::hash_table::{self, HashTable}; 16 | 17 | use crate::DefaultHashBuilder; 18 | 19 | pub enum TryReserveError { 20 | CapacityOverflow, 21 | AllocError { layout: Layout }, 22 | } 23 | 24 | /// A version of `HashMap` that has a user controllable order for its entries. 25 | /// 26 | /// It achieves this by keeping its entries in an internal linked list and using a `HashMap` to 27 | /// point at nodes in this linked list. 28 | /// 29 | /// The order of entries defaults to "insertion order", but the user can also modify the order of 30 | /// existing entries by manually moving them to the front or back. 31 | /// 32 | /// There are two kinds of methods that modify the order of the internal list: 33 | /// 34 | /// * Methods that have names like `to_front` and `to_back` will unsurprisingly move an existing 35 | /// entry to the front or back 36 | /// * Methods that have the word `insert` will insert a new entry ot the back of the list, and if 37 | /// that method might replace an entry, that method will *also move that existing entry to the 38 | /// back*. 39 | pub struct LinkedHashMap { 40 | table: HashTable>>, 41 | // We always need to keep our custom hash builder outside of the HashTable, because it doesn't 42 | // know how to do any hashing itself. 43 | hash_builder: S, 44 | // Circular linked list of nodes. If `values` is non-null, it will point to a "guard node" 45 | // which will never have an initialized key or value, `values.prev` will contain the last key / 46 | // value in the list, `values.next` will contain the first key / value in the list. 47 | values: Option>>, 48 | // *Singly* linked list of free nodes. The `prev` pointers in the free list should be assumed 49 | // invalid. 50 | free: Option>>, 51 | } 52 | 53 | impl LinkedHashMap { 54 | #[inline] 55 | pub fn new() -> Self { 56 | Self { 57 | hash_builder: DefaultHashBuilder::default(), 58 | table: HashTable::new(), 59 | values: None, 60 | free: None, 61 | } 62 | } 63 | 64 | #[inline] 65 | pub fn with_capacity(capacity: usize) -> Self { 66 | Self { 67 | hash_builder: DefaultHashBuilder::default(), 68 | table: HashTable::with_capacity(capacity), 69 | values: None, 70 | free: None, 71 | } 72 | } 73 | } 74 | 75 | impl LinkedHashMap { 76 | #[inline] 77 | pub fn with_hasher(hash_builder: S) -> Self { 78 | Self { 79 | hash_builder, 80 | table: HashTable::new(), 81 | values: None, 82 | free: None, 83 | } 84 | } 85 | 86 | #[inline] 87 | pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { 88 | Self { 89 | hash_builder, 90 | table: HashTable::with_capacity(capacity), 91 | values: None, 92 | free: None, 93 | } 94 | } 95 | 96 | #[inline] 97 | pub fn len(&self) -> usize { 98 | self.table.len() 99 | } 100 | 101 | #[inline] 102 | pub fn is_empty(&self) -> bool { 103 | self.len() == 0 104 | } 105 | 106 | #[inline] 107 | pub fn clear(&mut self) { 108 | self.table.clear(); 109 | if let Some(mut values) = self.values { 110 | unsafe { 111 | drop_value_nodes(values); 112 | values.as_mut().links.value = ValueLinks { 113 | prev: values, 114 | next: values, 115 | }; 116 | } 117 | } 118 | } 119 | 120 | #[inline] 121 | pub fn iter(&self) -> Iter { 122 | let (head, tail) = if let Some(values) = self.values { 123 | unsafe { 124 | let ValueLinks { next, prev } = values.as_ref().links.value; 125 | (next.as_ptr(), prev.as_ptr()) 126 | } 127 | } else { 128 | (ptr::null_mut(), ptr::null_mut()) 129 | }; 130 | 131 | Iter { 132 | head, 133 | tail, 134 | remaining: self.len(), 135 | marker: PhantomData, 136 | } 137 | } 138 | 139 | #[inline] 140 | pub fn iter_mut(&mut self) -> IterMut { 141 | let (head, tail) = if let Some(values) = self.values { 142 | unsafe { 143 | let ValueLinks { next, prev } = values.as_ref().links.value; 144 | (Some(next), Some(prev)) 145 | } 146 | } else { 147 | (None, None) 148 | }; 149 | 150 | IterMut { 151 | head, 152 | tail, 153 | remaining: self.len(), 154 | marker: PhantomData, 155 | } 156 | } 157 | 158 | #[inline] 159 | pub fn drain(&mut self) -> Drain<'_, K, V> { 160 | unsafe { 161 | let (head, tail) = if let Some(mut values) = self.values { 162 | let ValueLinks { next, prev } = values.as_ref().links.value; 163 | values.as_mut().links.value = ValueLinks { 164 | next: values, 165 | prev: values, 166 | }; 167 | (Some(next), Some(prev)) 168 | } else { 169 | (None, None) 170 | }; 171 | let len = self.len(); 172 | 173 | self.table.clear(); 174 | 175 | Drain { 176 | free: (&mut self.free).into(), 177 | head, 178 | tail, 179 | remaining: len, 180 | marker: PhantomData, 181 | } 182 | } 183 | } 184 | 185 | #[inline] 186 | pub fn keys(&self) -> Keys { 187 | Keys { inner: self.iter() } 188 | } 189 | 190 | #[inline] 191 | pub fn values(&self) -> Values { 192 | Values { inner: self.iter() } 193 | } 194 | 195 | #[inline] 196 | pub fn values_mut(&mut self) -> ValuesMut { 197 | ValuesMut { 198 | inner: self.iter_mut(), 199 | } 200 | } 201 | 202 | #[inline] 203 | pub fn front(&self) -> Option<(&K, &V)> { 204 | if self.is_empty() { 205 | return None; 206 | } 207 | unsafe { 208 | let front = (*self.values.as_ptr()).links.value.next.as_ptr(); 209 | let (key, value) = (*front).entry_ref(); 210 | Some((key, value)) 211 | } 212 | } 213 | 214 | #[inline] 215 | pub fn back(&self) -> Option<(&K, &V)> { 216 | if self.is_empty() { 217 | return None; 218 | } 219 | unsafe { 220 | let back = &*(*self.values.as_ptr()).links.value.prev.as_ptr(); 221 | let (key, value) = (*back).entry_ref(); 222 | Some((key, value)) 223 | } 224 | } 225 | 226 | #[inline] 227 | pub fn retain(&mut self, mut f: F) 228 | where 229 | F: FnMut(&K, &mut V) -> bool, 230 | { 231 | let free = self.free; 232 | let mut drop_filtered_values = DropFilteredValues { 233 | free: &mut self.free, 234 | cur_free: free, 235 | }; 236 | 237 | self.table.retain(|&mut node| unsafe { 238 | let (k, v) = (*node.as_ptr()).entry_mut(); 239 | if f(k, v) { 240 | true 241 | } else { 242 | drop_filtered_values.drop_later(node); 243 | false 244 | } 245 | }); 246 | } 247 | 248 | #[inline] 249 | pub fn hasher(&self) -> &S { 250 | &self.hash_builder 251 | } 252 | 253 | #[inline] 254 | pub fn capacity(&self) -> usize { 255 | self.table.capacity() 256 | } 257 | } 258 | 259 | impl LinkedHashMap 260 | where 261 | K: Eq + Hash, 262 | S: BuildHasher, 263 | { 264 | #[inline] 265 | pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> { 266 | match self.raw_entry_mut().from_key(&key) { 267 | RawEntryMut::Occupied(occupied) => Entry::Occupied(OccupiedEntry { 268 | key, 269 | raw_entry: occupied, 270 | }), 271 | RawEntryMut::Vacant(vacant) => Entry::Vacant(VacantEntry { 272 | key, 273 | raw_entry: vacant, 274 | }), 275 | } 276 | } 277 | 278 | #[inline] 279 | pub fn get(&self, k: &Q) -> Option<&V> 280 | where 281 | K: Borrow, 282 | Q: Hash + Eq + ?Sized, 283 | { 284 | self.raw_entry().from_key(k).map(|(_, v)| v) 285 | } 286 | 287 | #[inline] 288 | pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> 289 | where 290 | K: Borrow, 291 | Q: Hash + Eq + ?Sized, 292 | { 293 | self.raw_entry().from_key(k) 294 | } 295 | 296 | #[inline] 297 | pub fn contains_key(&self, k: &Q) -> bool 298 | where 299 | K: Borrow, 300 | Q: Hash + Eq + ?Sized, 301 | { 302 | self.get(k).is_some() 303 | } 304 | 305 | #[inline] 306 | pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> 307 | where 308 | K: Borrow, 309 | Q: Hash + Eq + ?Sized, 310 | { 311 | match self.raw_entry_mut().from_key(k) { 312 | RawEntryMut::Occupied(occupied) => Some(occupied.into_mut()), 313 | RawEntryMut::Vacant(_) => None, 314 | } 315 | } 316 | 317 | /// Inserts the given key / value pair at the *back* of the internal linked list. 318 | /// 319 | /// Returns the previously set value, if one existed prior to this call. After this call, 320 | /// calling `LinkedHashMap::back` will return a reference to this key / value pair. 321 | #[inline] 322 | pub fn insert(&mut self, k: K, v: V) -> Option { 323 | match self.raw_entry_mut().from_key(&k) { 324 | RawEntryMut::Occupied(mut occupied) => { 325 | occupied.to_back(); 326 | Some(occupied.replace_value(v)) 327 | } 328 | RawEntryMut::Vacant(vacant) => { 329 | vacant.insert(k, v); 330 | None 331 | } 332 | } 333 | } 334 | 335 | /// If the given key is not in this map, inserts the key / value pair at the *back* of the 336 | /// internal linked list and returns `None`, otherwise, replaces the existing value with the 337 | /// given value *without* moving the entry in the internal linked list and returns the previous 338 | /// value. 339 | #[inline] 340 | pub fn replace(&mut self, k: K, v: V) -> Option { 341 | match self.raw_entry_mut().from_key(&k) { 342 | RawEntryMut::Occupied(mut occupied) => Some(occupied.replace_value(v)), 343 | RawEntryMut::Vacant(vacant) => { 344 | vacant.insert(k, v); 345 | None 346 | } 347 | } 348 | } 349 | 350 | #[inline] 351 | pub fn remove(&mut self, k: &Q) -> Option 352 | where 353 | K: Borrow, 354 | Q: Hash + Eq + ?Sized, 355 | { 356 | match self.raw_entry_mut().from_key(k) { 357 | RawEntryMut::Occupied(occupied) => Some(occupied.remove()), 358 | RawEntryMut::Vacant(_) => None, 359 | } 360 | } 361 | 362 | #[inline] 363 | pub fn remove_entry(&mut self, k: &Q) -> Option<(K, V)> 364 | where 365 | K: Borrow, 366 | Q: Hash + Eq + ?Sized, 367 | { 368 | match self.raw_entry_mut().from_key(k) { 369 | RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry()), 370 | RawEntryMut::Vacant(_) => None, 371 | } 372 | } 373 | 374 | #[inline] 375 | pub fn pop_front(&mut self) -> Option<(K, V)> { 376 | if self.is_empty() { 377 | return None; 378 | } 379 | unsafe { 380 | let front = (*self.values.as_ptr()).links.value.next; 381 | let hash = hash_node(&self.hash_builder, front); 382 | match self 383 | .raw_entry_mut() 384 | .from_hash(hash, |k| k.eq(front.as_ref().key_ref())) 385 | { 386 | RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry()), 387 | RawEntryMut::Vacant(_) => None, 388 | } 389 | } 390 | } 391 | 392 | #[inline] 393 | pub fn pop_back(&mut self) -> Option<(K, V)> { 394 | if self.is_empty() { 395 | return None; 396 | } 397 | unsafe { 398 | let back = (*self.values.as_ptr()).links.value.prev; 399 | let hash = hash_node(&self.hash_builder, back); 400 | match self 401 | .raw_entry_mut() 402 | .from_hash(hash, |k| k.eq(back.as_ref().key_ref())) 403 | { 404 | RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry()), 405 | RawEntryMut::Vacant(_) => None, 406 | } 407 | } 408 | } 409 | 410 | /// If an entry with this key exists, move it to the front of the list and return a reference to 411 | /// the value. 412 | #[inline] 413 | pub fn to_front(&mut self, k: &Q) -> Option<&mut V> 414 | where 415 | K: Borrow, 416 | Q: Hash + Eq + ?Sized, 417 | { 418 | match self.raw_entry_mut().from_key(k) { 419 | RawEntryMut::Occupied(mut occupied) => { 420 | occupied.to_front(); 421 | Some(occupied.into_mut()) 422 | } 423 | RawEntryMut::Vacant(_) => None, 424 | } 425 | } 426 | 427 | /// If an entry with this key exists, move it to the back of the list and return a reference to 428 | /// the value. 429 | #[inline] 430 | pub fn to_back(&mut self, k: &Q) -> Option<&mut V> 431 | where 432 | K: Borrow, 433 | Q: Hash + Eq + ?Sized, 434 | { 435 | match self.raw_entry_mut().from_key(k) { 436 | RawEntryMut::Occupied(mut occupied) => { 437 | occupied.to_back(); 438 | Some(occupied.into_mut()) 439 | } 440 | RawEntryMut::Vacant(_) => None, 441 | } 442 | } 443 | 444 | #[inline] 445 | pub fn reserve(&mut self, additional: usize) { 446 | let hash_builder = &self.hash_builder; 447 | self.table 448 | .reserve(additional, move |&n| unsafe { hash_node(hash_builder, n) }); 449 | } 450 | 451 | #[inline] 452 | pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { 453 | let hash_builder = &self.hash_builder; 454 | self.table 455 | .try_reserve(additional, move |&n| unsafe { hash_node(hash_builder, n) }) 456 | .map_err(|e| match e { 457 | hashbrown::TryReserveError::CapacityOverflow => TryReserveError::CapacityOverflow, 458 | hashbrown::TryReserveError::AllocError { layout } => { 459 | TryReserveError::AllocError { layout } 460 | } 461 | }) 462 | } 463 | 464 | #[inline] 465 | pub fn shrink_to_fit(&mut self) { 466 | let hash_builder = &self.hash_builder; 467 | unsafe { 468 | self.table 469 | .shrink_to_fit(move |&n| hash_node(hash_builder, n)); 470 | drop_free_nodes(self.free.take()); 471 | } 472 | } 473 | 474 | pub fn retain_with_order(&mut self, mut f: F) 475 | where 476 | F: FnMut(&K, &mut V) -> bool, 477 | { 478 | let free = self.free; 479 | let mut drop_filtered_values = DropFilteredValues { 480 | free: &mut self.free, 481 | cur_free: free, 482 | }; 483 | 484 | if let Some(values) = self.values { 485 | unsafe { 486 | let mut cur = values.as_ref().links.value.next; 487 | while cur != values { 488 | let next = cur.as_ref().links.value.next; 489 | let filter = { 490 | let (k, v) = (*cur.as_ptr()).entry_mut(); 491 | !f(k, v) 492 | }; 493 | if filter { 494 | let k = (*cur.as_ptr()).key_ref(); 495 | let hash = hash_key(&self.hash_builder, k); 496 | self.table 497 | .find_entry(hash, |o| (*o).as_ref().key_ref().eq(k)) 498 | .unwrap() 499 | .remove(); 500 | drop_filtered_values.drop_later(cur); 501 | } 502 | cur = next; 503 | } 504 | } 505 | } 506 | } 507 | 508 | // Returns the `CursorMut` over the _guard_ node. 509 | fn cursor_mut(&mut self) -> CursorMut { 510 | unsafe { ensure_guard_node(&mut self.values) }; 511 | CursorMut { 512 | cur: self.values.as_ptr(), 513 | hash_builder: &self.hash_builder, 514 | free: &mut self.free, 515 | values: &mut self.values, 516 | table: &mut self.table, 517 | } 518 | } 519 | 520 | /// Returns the `CursorMut` over the front node. 521 | /// 522 | /// Note: The `CursorMut` is pointing to the _guard_ node in an empty `LinkedHashMap` and 523 | /// will always return `None` as its current element, regardless of any move in any 524 | /// direction. 525 | pub fn cursor_front_mut(&mut self) -> CursorMut { 526 | let mut c = self.cursor_mut(); 527 | c.move_next(); 528 | c 529 | } 530 | 531 | /// Returns the `CursorMut` over the back node. 532 | /// 533 | /// Note: The `CursorMut` is pointing to the _guard_ node in an empty `LinkedHashMap` and 534 | /// will always return `None` as its current element, regardless of any move in any 535 | /// direction. 536 | pub fn cursor_back_mut(&mut self) -> CursorMut { 537 | let mut c = self.cursor_mut(); 538 | c.move_prev(); 539 | c 540 | } 541 | } 542 | 543 | impl LinkedHashMap 544 | where 545 | S: BuildHasher, 546 | { 547 | #[inline] 548 | pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { 549 | RawEntryBuilder { map: self } 550 | } 551 | 552 | #[inline] 553 | pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { 554 | RawEntryBuilderMut { map: self } 555 | } 556 | } 557 | 558 | impl Default for LinkedHashMap 559 | where 560 | S: Default, 561 | { 562 | #[inline] 563 | fn default() -> Self { 564 | Self::with_hasher(S::default()) 565 | } 566 | } 567 | 568 | impl FromIterator<(K, V)> for LinkedHashMap { 569 | #[inline] 570 | fn from_iter>(iter: I) -> Self { 571 | let iter = iter.into_iter(); 572 | let mut map = Self::with_capacity_and_hasher(iter.size_hint().0, S::default()); 573 | map.extend(iter); 574 | map 575 | } 576 | } 577 | 578 | impl fmt::Debug for LinkedHashMap 579 | where 580 | K: fmt::Debug, 581 | V: fmt::Debug, 582 | { 583 | #[inline] 584 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 585 | f.debug_map().entries(self).finish() 586 | } 587 | } 588 | 589 | impl PartialEq for LinkedHashMap { 590 | #[inline] 591 | fn eq(&self, other: &Self) -> bool { 592 | self.len() == other.len() && self.iter().eq(other) 593 | } 594 | } 595 | 596 | impl Eq for LinkedHashMap {} 597 | 598 | impl PartialOrd 599 | for LinkedHashMap 600 | { 601 | #[inline] 602 | fn partial_cmp(&self, other: &Self) -> Option { 603 | self.iter().partial_cmp(other) 604 | } 605 | 606 | #[inline] 607 | fn lt(&self, other: &Self) -> bool { 608 | self.iter().lt(other) 609 | } 610 | 611 | #[inline] 612 | fn le(&self, other: &Self) -> bool { 613 | self.iter().le(other) 614 | } 615 | 616 | #[inline] 617 | fn ge(&self, other: &Self) -> bool { 618 | self.iter().ge(other) 619 | } 620 | 621 | #[inline] 622 | fn gt(&self, other: &Self) -> bool { 623 | self.iter().gt(other) 624 | } 625 | } 626 | 627 | impl Ord for LinkedHashMap { 628 | #[inline] 629 | fn cmp(&self, other: &Self) -> Ordering { 630 | self.iter().cmp(other) 631 | } 632 | } 633 | 634 | impl Hash for LinkedHashMap { 635 | #[inline] 636 | fn hash(&self, h: &mut H) { 637 | for e in self.iter() { 638 | e.hash(h); 639 | } 640 | } 641 | } 642 | 643 | impl Drop for LinkedHashMap { 644 | #[inline] 645 | fn drop(&mut self) { 646 | unsafe { 647 | if let Some(values) = self.values { 648 | drop_value_nodes(values); 649 | let _ = Box::from_raw(values.as_ptr()); 650 | } 651 | drop_free_nodes(self.free); 652 | } 653 | } 654 | } 655 | 656 | unsafe impl Send for LinkedHashMap {} 657 | unsafe impl Sync for LinkedHashMap {} 658 | 659 | impl<'a, K, V, S, Q> Index<&'a Q> for LinkedHashMap 660 | where 661 | K: Hash + Eq + Borrow, 662 | S: BuildHasher, 663 | Q: Eq + Hash + ?Sized, 664 | { 665 | type Output = V; 666 | 667 | #[inline] 668 | fn index(&self, index: &'a Q) -> &V { 669 | self.get(index).expect("no entry found for key") 670 | } 671 | } 672 | 673 | impl<'a, K, V, S, Q> IndexMut<&'a Q> for LinkedHashMap 674 | where 675 | K: Hash + Eq + Borrow, 676 | S: BuildHasher, 677 | Q: Eq + Hash + ?Sized, 678 | { 679 | #[inline] 680 | fn index_mut(&mut self, index: &'a Q) -> &mut V { 681 | self.get_mut(index).expect("no entry found for key") 682 | } 683 | } 684 | 685 | impl Clone for LinkedHashMap { 686 | #[inline] 687 | fn clone(&self) -> Self { 688 | let mut map = Self::with_hasher(self.hash_builder.clone()); 689 | map.extend(self.iter().map(|(k, v)| (k.clone(), v.clone()))); 690 | map 691 | } 692 | } 693 | 694 | impl Extend<(K, V)> for LinkedHashMap { 695 | #[inline] 696 | fn extend>(&mut self, iter: I) { 697 | for (k, v) in iter { 698 | self.insert(k, v); 699 | } 700 | } 701 | } 702 | 703 | impl<'a, K, V, S> Extend<(&'a K, &'a V)> for LinkedHashMap 704 | where 705 | K: 'a + Hash + Eq + Copy, 706 | V: 'a + Copy, 707 | S: BuildHasher, 708 | { 709 | #[inline] 710 | fn extend>(&mut self, iter: I) { 711 | for (&k, &v) in iter { 712 | self.insert(k, v); 713 | } 714 | } 715 | } 716 | 717 | pub enum Entry<'a, K, V, S> { 718 | Occupied(OccupiedEntry<'a, K, V, S>), 719 | Vacant(VacantEntry<'a, K, V, S>), 720 | } 721 | 722 | impl fmt::Debug for Entry<'_, K, V, S> { 723 | #[inline] 724 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 725 | match *self { 726 | Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), 727 | Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(), 728 | } 729 | } 730 | } 731 | 732 | impl<'a, K, V, S> Entry<'a, K, V, S> { 733 | /// If this entry is vacant, inserts a new entry with the given value and returns a reference to 734 | /// it. 735 | /// 736 | /// If this entry is occupied, this method *moves the occupied entry to the back of the internal 737 | /// linked list* and returns a reference to the existing value. 738 | #[inline] 739 | pub fn or_insert(self, default: V) -> &'a mut V 740 | where 741 | K: Hash, 742 | S: BuildHasher, 743 | { 744 | match self { 745 | Entry::Occupied(mut entry) => { 746 | entry.to_back(); 747 | entry.into_mut() 748 | } 749 | Entry::Vacant(entry) => entry.insert(default), 750 | } 751 | } 752 | 753 | /// Similar to `Entry::or_insert`, but accepts a function to construct a new value if this entry 754 | /// is vacant. 755 | #[inline] 756 | pub fn or_insert_with V>(self, default: F) -> &'a mut V 757 | where 758 | K: Hash, 759 | S: BuildHasher, 760 | { 761 | match self { 762 | Entry::Occupied(mut entry) => { 763 | entry.to_back(); 764 | entry.into_mut() 765 | } 766 | Entry::Vacant(entry) => entry.insert(default()), 767 | } 768 | } 769 | 770 | #[inline] 771 | pub fn key(&self) -> &K { 772 | match *self { 773 | Entry::Occupied(ref entry) => entry.key(), 774 | Entry::Vacant(ref entry) => entry.key(), 775 | } 776 | } 777 | 778 | #[inline] 779 | pub fn and_modify(self, f: F) -> Self 780 | where 781 | F: FnOnce(&mut V), 782 | { 783 | match self { 784 | Entry::Occupied(mut entry) => { 785 | f(entry.get_mut()); 786 | Entry::Occupied(entry) 787 | } 788 | Entry::Vacant(entry) => Entry::Vacant(entry), 789 | } 790 | } 791 | } 792 | 793 | pub struct OccupiedEntry<'a, K, V, S> { 794 | key: K, 795 | raw_entry: RawOccupiedEntryMut<'a, K, V, S>, 796 | } 797 | 798 | impl fmt::Debug for OccupiedEntry<'_, K, V, S> { 799 | #[inline] 800 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 801 | f.debug_struct("OccupiedEntry") 802 | .field("key", self.key()) 803 | .field("value", self.get()) 804 | .finish() 805 | } 806 | } 807 | 808 | impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> { 809 | #[inline] 810 | pub fn key(&self) -> &K { 811 | self.raw_entry.key() 812 | } 813 | 814 | #[inline] 815 | pub fn remove_entry(self) -> (K, V) { 816 | self.raw_entry.remove_entry() 817 | } 818 | 819 | #[inline] 820 | pub fn get(&self) -> &V { 821 | self.raw_entry.get() 822 | } 823 | 824 | #[inline] 825 | pub fn get_mut(&mut self) -> &mut V { 826 | self.raw_entry.get_mut() 827 | } 828 | 829 | #[inline] 830 | pub fn into_mut(self) -> &'a mut V { 831 | self.raw_entry.into_mut() 832 | } 833 | 834 | #[inline] 835 | pub fn to_back(&mut self) { 836 | self.raw_entry.to_back() 837 | } 838 | 839 | #[inline] 840 | pub fn to_front(&mut self) { 841 | self.raw_entry.to_front() 842 | } 843 | 844 | /// Replaces this entry's value with the provided value. 845 | /// 846 | /// Similarly to `LinkedHashMap::insert`, this moves the existing entry to the back of the 847 | /// internal linked list. 848 | #[inline] 849 | pub fn insert(&mut self, value: V) -> V { 850 | self.raw_entry.to_back(); 851 | self.raw_entry.replace_value(value) 852 | } 853 | 854 | #[inline] 855 | pub fn remove(self) -> V { 856 | self.raw_entry.remove() 857 | } 858 | 859 | /// Similar to `OccupiedEntry::replace_entry`, but *does* move the entry to the back of the 860 | /// internal linked list. 861 | #[inline] 862 | pub fn insert_entry(mut self, value: V) -> (K, V) { 863 | self.raw_entry.to_back(); 864 | self.replace_entry(value) 865 | } 866 | 867 | /// Returns a `CursorMut` over the current entry. 868 | #[inline] 869 | pub fn cursor_mut(self) -> CursorMut<'a, K, V, S> 870 | where 871 | K: Eq + Hash, 872 | S: BuildHasher, 873 | { 874 | self.raw_entry.cursor_mut() 875 | } 876 | 877 | /// Replaces the entry's key with the key provided to `LinkedHashMap::entry`, and replaces the 878 | /// entry's value with the given `value` parameter. 879 | /// 880 | /// Does *not* move the entry to the back of the internal linked list. 881 | pub fn replace_entry(mut self, value: V) -> (K, V) { 882 | let old_key = mem::replace(self.raw_entry.key_mut(), self.key); 883 | let old_value = mem::replace(self.raw_entry.get_mut(), value); 884 | (old_key, old_value) 885 | } 886 | 887 | /// Replaces this entry's key with the key provided to `LinkedHashMap::entry`. 888 | /// 889 | /// Does *not* move the entry to the back of the internal linked list. 890 | #[inline] 891 | pub fn replace_key(mut self) -> K { 892 | mem::replace(self.raw_entry.key_mut(), self.key) 893 | } 894 | } 895 | 896 | pub struct VacantEntry<'a, K, V, S> { 897 | key: K, 898 | raw_entry: RawVacantEntryMut<'a, K, V, S>, 899 | } 900 | 901 | impl fmt::Debug for VacantEntry<'_, K, V, S> { 902 | #[inline] 903 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 904 | f.debug_tuple("VacantEntry").field(self.key()).finish() 905 | } 906 | } 907 | 908 | impl<'a, K, V, S> VacantEntry<'a, K, V, S> { 909 | #[inline] 910 | pub fn key(&self) -> &K { 911 | &self.key 912 | } 913 | 914 | #[inline] 915 | pub fn into_key(self) -> K { 916 | self.key 917 | } 918 | 919 | /// Insert's the key for this vacant entry paired with the given value as a new entry at the 920 | /// *back* of the internal linked list. 921 | #[inline] 922 | pub fn insert(self, value: V) -> &'a mut V 923 | where 924 | K: Hash, 925 | S: BuildHasher, 926 | { 927 | self.raw_entry.insert(self.key, value).1 928 | } 929 | } 930 | 931 | pub struct RawEntryBuilder<'a, K, V, S> { 932 | map: &'a LinkedHashMap, 933 | } 934 | 935 | impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> 936 | where 937 | S: BuildHasher, 938 | { 939 | #[inline] 940 | pub fn from_key(self, k: &Q) -> Option<(&'a K, &'a V)> 941 | where 942 | K: Borrow, 943 | Q: Hash + Eq + ?Sized, 944 | { 945 | let hash = hash_key(&self.map.hash_builder, k); 946 | self.from_key_hashed_nocheck(hash, k) 947 | } 948 | 949 | #[inline] 950 | pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> Option<(&'a K, &'a V)> 951 | where 952 | K: Borrow, 953 | Q: Hash + Eq + ?Sized, 954 | { 955 | self.from_hash(hash, move |o| k.eq(o.borrow())) 956 | } 957 | 958 | #[inline] 959 | pub fn from_hash( 960 | self, 961 | hash: u64, 962 | mut is_match: impl FnMut(&K) -> bool, 963 | ) -> Option<(&'a K, &'a V)> { 964 | unsafe { 965 | let node = self 966 | .map 967 | .table 968 | .find(hash, move |k| is_match((*k).as_ref().key_ref()))?; 969 | 970 | let (key, value) = (*node.as_ptr()).entry_ref(); 971 | Some((key, value)) 972 | } 973 | } 974 | } 975 | 976 | pub struct RawEntryBuilderMut<'a, K, V, S> { 977 | map: &'a mut LinkedHashMap, 978 | } 979 | 980 | impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> 981 | where 982 | S: BuildHasher, 983 | { 984 | #[inline] 985 | pub fn from_key(self, k: &Q) -> RawEntryMut<'a, K, V, S> 986 | where 987 | K: Borrow, 988 | Q: Hash + Eq + ?Sized, 989 | { 990 | let hash = hash_key(&self.map.hash_builder, k); 991 | self.from_key_hashed_nocheck(hash, k) 992 | } 993 | 994 | #[inline] 995 | pub fn from_key_hashed_nocheck(self, hash: u64, k: &Q) -> RawEntryMut<'a, K, V, S> 996 | where 997 | K: Borrow, 998 | Q: Hash + Eq + ?Sized, 999 | { 1000 | self.from_hash(hash, move |o| k.eq(o.borrow())) 1001 | } 1002 | 1003 | #[inline] 1004 | pub fn from_hash( 1005 | self, 1006 | hash: u64, 1007 | mut is_match: impl FnMut(&K) -> bool, 1008 | ) -> RawEntryMut<'a, K, V, S> { 1009 | let entry = self 1010 | .map 1011 | .table 1012 | .find_entry(hash, move |k| is_match(unsafe { (*k).as_ref().key_ref() })); 1013 | 1014 | match entry { 1015 | Ok(occupied) => RawEntryMut::Occupied(RawOccupiedEntryMut { 1016 | hash_builder: &self.map.hash_builder, 1017 | free: &mut self.map.free, 1018 | values: &mut self.map.values, 1019 | entry: occupied, 1020 | }), 1021 | Err(absent) => RawEntryMut::Vacant(RawVacantEntryMut { 1022 | hash_builder: &self.map.hash_builder, 1023 | values: &mut self.map.values, 1024 | free: &mut self.map.free, 1025 | entry: absent, 1026 | }), 1027 | } 1028 | } 1029 | } 1030 | 1031 | pub enum RawEntryMut<'a, K, V, S> { 1032 | Occupied(RawOccupiedEntryMut<'a, K, V, S>), 1033 | Vacant(RawVacantEntryMut<'a, K, V, S>), 1034 | } 1035 | 1036 | impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { 1037 | /// Similarly to `Entry::or_insert`, if this entry is occupied, it will move the existing entry 1038 | /// to the back of the internal linked list. 1039 | #[inline] 1040 | pub fn or_insert(self, default_key: K, default_val: V) -> (&'a mut K, &'a mut V) 1041 | where 1042 | K: Hash, 1043 | S: BuildHasher, 1044 | { 1045 | match self { 1046 | RawEntryMut::Occupied(mut entry) => { 1047 | entry.to_back(); 1048 | entry.into_key_value() 1049 | } 1050 | RawEntryMut::Vacant(entry) => entry.insert(default_key, default_val), 1051 | } 1052 | } 1053 | 1054 | /// Similarly to `Entry::or_insert_with`, if this entry is occupied, it will move the existing 1055 | /// entry to the back of the internal linked list. 1056 | #[inline] 1057 | pub fn or_insert_with(self, default: F) -> (&'a mut K, &'a mut V) 1058 | where 1059 | F: FnOnce() -> (K, V), 1060 | K: Hash, 1061 | S: BuildHasher, 1062 | { 1063 | match self { 1064 | RawEntryMut::Occupied(mut entry) => { 1065 | entry.to_back(); 1066 | entry.into_key_value() 1067 | } 1068 | RawEntryMut::Vacant(entry) => { 1069 | let (k, v) = default(); 1070 | entry.insert(k, v) 1071 | } 1072 | } 1073 | } 1074 | 1075 | #[inline] 1076 | pub fn and_modify(self, f: F) -> Self 1077 | where 1078 | F: FnOnce(&mut K, &mut V), 1079 | { 1080 | match self { 1081 | RawEntryMut::Occupied(mut entry) => { 1082 | { 1083 | let (k, v) = entry.get_key_value_mut(); 1084 | f(k, v); 1085 | } 1086 | RawEntryMut::Occupied(entry) 1087 | } 1088 | RawEntryMut::Vacant(entry) => RawEntryMut::Vacant(entry), 1089 | } 1090 | } 1091 | } 1092 | 1093 | pub struct RawOccupiedEntryMut<'a, K, V, S> { 1094 | hash_builder: &'a S, 1095 | free: &'a mut Option>>, 1096 | values: &'a mut Option>>, 1097 | entry: hash_table::OccupiedEntry<'a, NonNull>>, 1098 | } 1099 | 1100 | impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { 1101 | #[inline] 1102 | pub fn key(&self) -> &K { 1103 | self.get_key_value().0 1104 | } 1105 | 1106 | #[inline] 1107 | pub fn key_mut(&mut self) -> &mut K { 1108 | self.get_key_value_mut().0 1109 | } 1110 | 1111 | #[inline] 1112 | pub fn into_key(self) -> &'a mut K { 1113 | self.into_key_value().0 1114 | } 1115 | 1116 | #[inline] 1117 | pub fn get(&self) -> &V { 1118 | self.get_key_value().1 1119 | } 1120 | 1121 | #[inline] 1122 | pub fn get_mut(&mut self) -> &mut V { 1123 | self.get_key_value_mut().1 1124 | } 1125 | 1126 | #[inline] 1127 | pub fn into_mut(self) -> &'a mut V { 1128 | self.into_key_value().1 1129 | } 1130 | 1131 | #[inline] 1132 | pub fn get_key_value(&self) -> (&K, &V) { 1133 | unsafe { 1134 | let node = *self.entry.get(); 1135 | let (key, value) = (*node.as_ptr()).entry_ref(); 1136 | (key, value) 1137 | } 1138 | } 1139 | 1140 | #[inline] 1141 | pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { 1142 | unsafe { 1143 | let node = *self.entry.get_mut(); 1144 | let (key, value) = (*node.as_ptr()).entry_mut(); 1145 | (key, value) 1146 | } 1147 | } 1148 | 1149 | #[inline] 1150 | pub fn into_key_value(self) -> (&'a mut K, &'a mut V) { 1151 | unsafe { 1152 | let node = *self.entry.into_mut(); 1153 | let (key, value) = (*node.as_ptr()).entry_mut(); 1154 | (key, value) 1155 | } 1156 | } 1157 | 1158 | #[inline] 1159 | pub fn to_back(&mut self) { 1160 | unsafe { 1161 | let node = *self.entry.get_mut(); 1162 | detach_node(node); 1163 | attach_before(node, NonNull::new_unchecked(self.values.as_ptr())); 1164 | } 1165 | } 1166 | 1167 | #[inline] 1168 | pub fn to_front(&mut self) { 1169 | unsafe { 1170 | let node = *self.entry.get_mut(); 1171 | detach_node(node); 1172 | attach_before(node, (*self.values.as_ptr()).links.value.next); 1173 | } 1174 | } 1175 | 1176 | #[inline] 1177 | pub fn replace_value(&mut self, value: V) -> V { 1178 | unsafe { 1179 | let mut node = *self.entry.get_mut(); 1180 | mem::replace(&mut node.as_mut().entry_mut().1, value) 1181 | } 1182 | } 1183 | 1184 | #[inline] 1185 | pub fn replace_key(&mut self, key: K) -> K { 1186 | unsafe { 1187 | let mut node = *self.entry.get_mut(); 1188 | mem::replace(&mut node.as_mut().entry_mut().0, key) 1189 | } 1190 | } 1191 | 1192 | #[inline] 1193 | pub fn remove(self) -> V { 1194 | self.remove_entry().1 1195 | } 1196 | 1197 | #[inline] 1198 | pub fn remove_entry(self) -> (K, V) { 1199 | let node = self.entry.remove().0; 1200 | unsafe { remove_node(self.free, node) } 1201 | } 1202 | 1203 | /// Returns a `CursorMut` over the current entry. 1204 | #[inline] 1205 | pub fn cursor_mut(self) -> CursorMut<'a, K, V, S> 1206 | where 1207 | K: Eq + Hash, 1208 | S: BuildHasher, 1209 | { 1210 | CursorMut { 1211 | cur: self.entry.get().as_ptr(), 1212 | hash_builder: self.hash_builder, 1213 | free: self.free, 1214 | values: self.values, 1215 | table: self.entry.into_table(), 1216 | } 1217 | } 1218 | } 1219 | 1220 | pub struct RawVacantEntryMut<'a, K, V, S> { 1221 | hash_builder: &'a S, 1222 | values: &'a mut Option>>, 1223 | free: &'a mut Option>>, 1224 | entry: hash_table::AbsentEntry<'a, NonNull>>, 1225 | } 1226 | 1227 | impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { 1228 | #[inline] 1229 | pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) 1230 | where 1231 | K: Hash, 1232 | S: BuildHasher, 1233 | { 1234 | let hash = hash_key(self.hash_builder, &key); 1235 | self.insert_hashed_nocheck(hash, key, value) 1236 | } 1237 | 1238 | #[inline] 1239 | pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) 1240 | where 1241 | K: Hash, 1242 | S: BuildHasher, 1243 | { 1244 | let hash_builder = self.hash_builder; 1245 | self.insert_with_hasher(hash, key, value, |k| hash_key(hash_builder, k)) 1246 | } 1247 | 1248 | #[inline] 1249 | pub fn insert_with_hasher( 1250 | self, 1251 | hash: u64, 1252 | key: K, 1253 | value: V, 1254 | hasher: impl Fn(&K) -> u64, 1255 | ) -> (&'a mut K, &'a mut V) 1256 | where 1257 | S: BuildHasher, 1258 | { 1259 | unsafe { 1260 | ensure_guard_node(self.values); 1261 | let mut new_node = allocate_node(self.free); 1262 | new_node.as_mut().put_entry((key, value)); 1263 | attach_before(new_node, NonNull::new_unchecked(self.values.as_ptr())); 1264 | 1265 | let node = self 1266 | .entry 1267 | .into_table() 1268 | .insert_unique(hash, new_node, move |k| hasher((*k).as_ref().key_ref())) 1269 | .into_mut(); 1270 | 1271 | let (key, value) = (*node.as_ptr()).entry_mut(); 1272 | (key, value) 1273 | } 1274 | } 1275 | } 1276 | 1277 | impl fmt::Debug for RawEntryBuilderMut<'_, K, V, S> { 1278 | #[inline] 1279 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1280 | f.debug_struct("RawEntryBuilder").finish() 1281 | } 1282 | } 1283 | 1284 | impl fmt::Debug for RawEntryMut<'_, K, V, S> { 1285 | #[inline] 1286 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1287 | match *self { 1288 | RawEntryMut::Vacant(ref v) => f.debug_tuple("RawEntry").field(v).finish(), 1289 | RawEntryMut::Occupied(ref o) => f.debug_tuple("RawEntry").field(o).finish(), 1290 | } 1291 | } 1292 | } 1293 | 1294 | impl fmt::Debug for RawOccupiedEntryMut<'_, K, V, S> { 1295 | #[inline] 1296 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1297 | f.debug_struct("RawOccupiedEntryMut") 1298 | .field("key", self.key()) 1299 | .field("value", self.get()) 1300 | .finish() 1301 | } 1302 | } 1303 | 1304 | impl fmt::Debug for RawVacantEntryMut<'_, K, V, S> { 1305 | #[inline] 1306 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1307 | f.debug_struct("RawVacantEntryMut").finish() 1308 | } 1309 | } 1310 | 1311 | impl fmt::Debug for RawEntryBuilder<'_, K, V, S> { 1312 | #[inline] 1313 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1314 | f.debug_struct("RawEntryBuilder").finish() 1315 | } 1316 | } 1317 | 1318 | unsafe impl Send for RawOccupiedEntryMut<'_, K, V, S> 1319 | where 1320 | K: Send, 1321 | V: Send, 1322 | S: Send, 1323 | { 1324 | } 1325 | 1326 | unsafe impl Sync for RawOccupiedEntryMut<'_, K, V, S> 1327 | where 1328 | K: Sync, 1329 | V: Sync, 1330 | S: Sync, 1331 | { 1332 | } 1333 | 1334 | unsafe impl Send for RawVacantEntryMut<'_, K, V, S> 1335 | where 1336 | K: Send, 1337 | V: Send, 1338 | S: Send, 1339 | { 1340 | } 1341 | 1342 | unsafe impl Sync for RawVacantEntryMut<'_, K, V, S> 1343 | where 1344 | K: Sync, 1345 | V: Sync, 1346 | S: Sync, 1347 | { 1348 | } 1349 | 1350 | pub struct Iter<'a, K, V> { 1351 | head: *const Node, 1352 | tail: *const Node, 1353 | remaining: usize, 1354 | marker: PhantomData<(&'a K, &'a V)>, 1355 | } 1356 | 1357 | pub struct IterMut<'a, K, V> { 1358 | head: Option>>, 1359 | tail: Option>>, 1360 | remaining: usize, 1361 | marker: PhantomData<(&'a K, &'a mut V)>, 1362 | } 1363 | 1364 | pub struct IntoIter { 1365 | head: Option>>, 1366 | tail: Option>>, 1367 | remaining: usize, 1368 | marker: PhantomData<(K, V)>, 1369 | } 1370 | 1371 | pub struct Drain<'a, K, V> { 1372 | free: NonNull>>>, 1373 | head: Option>>, 1374 | tail: Option>>, 1375 | remaining: usize, 1376 | // We want `Drain` to be covariant 1377 | marker: PhantomData<(K, V, &'a LinkedHashMap)>, 1378 | } 1379 | 1380 | impl IterMut<'_, K, V> { 1381 | #[inline] 1382 | pub(crate) fn iter(&self) -> Iter<'_, K, V> { 1383 | Iter { 1384 | head: self.head.as_ptr(), 1385 | tail: self.tail.as_ptr(), 1386 | remaining: self.remaining, 1387 | marker: PhantomData, 1388 | } 1389 | } 1390 | } 1391 | 1392 | impl IntoIter { 1393 | #[inline] 1394 | pub(crate) fn iter(&self) -> Iter<'_, K, V> { 1395 | Iter { 1396 | head: self.head.as_ptr(), 1397 | tail: self.tail.as_ptr(), 1398 | remaining: self.remaining, 1399 | marker: PhantomData, 1400 | } 1401 | } 1402 | } 1403 | 1404 | impl Drain<'_, K, V> { 1405 | #[inline] 1406 | pub(crate) fn iter(&self) -> Iter<'_, K, V> { 1407 | Iter { 1408 | head: self.head.as_ptr(), 1409 | tail: self.tail.as_ptr(), 1410 | remaining: self.remaining, 1411 | marker: PhantomData, 1412 | } 1413 | } 1414 | } 1415 | 1416 | unsafe impl Send for Iter<'_, K, V> 1417 | where 1418 | K: Sync, 1419 | V: Sync, 1420 | { 1421 | } 1422 | 1423 | unsafe impl Send for IterMut<'_, K, V> 1424 | where 1425 | K: Send, 1426 | V: Send, 1427 | { 1428 | } 1429 | 1430 | unsafe impl Send for IntoIter 1431 | where 1432 | K: Send, 1433 | V: Send, 1434 | { 1435 | } 1436 | 1437 | unsafe impl Send for Drain<'_, K, V> 1438 | where 1439 | K: Send, 1440 | V: Send, 1441 | { 1442 | } 1443 | 1444 | unsafe impl Sync for Iter<'_, K, V> 1445 | where 1446 | K: Sync, 1447 | V: Sync, 1448 | { 1449 | } 1450 | 1451 | unsafe impl Sync for IterMut<'_, K, V> 1452 | where 1453 | K: Sync, 1454 | V: Sync, 1455 | { 1456 | } 1457 | 1458 | unsafe impl Sync for IntoIter 1459 | where 1460 | K: Sync, 1461 | V: Sync, 1462 | { 1463 | } 1464 | 1465 | unsafe impl Sync for Drain<'_, K, V> 1466 | where 1467 | K: Sync, 1468 | V: Sync, 1469 | { 1470 | } 1471 | 1472 | impl Clone for Iter<'_, K, V> { 1473 | #[inline] 1474 | fn clone(&self) -> Self { 1475 | Iter { ..*self } 1476 | } 1477 | } 1478 | 1479 | impl fmt::Debug for Iter<'_, K, V> { 1480 | #[inline] 1481 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1482 | f.debug_list().entries(self.clone()).finish() 1483 | } 1484 | } 1485 | 1486 | impl fmt::Debug for IterMut<'_, K, V> 1487 | where 1488 | K: fmt::Debug, 1489 | V: fmt::Debug, 1490 | { 1491 | #[inline] 1492 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1493 | f.debug_list().entries(self.iter()).finish() 1494 | } 1495 | } 1496 | 1497 | impl fmt::Debug for IntoIter 1498 | where 1499 | K: fmt::Debug, 1500 | V: fmt::Debug, 1501 | { 1502 | #[inline] 1503 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1504 | f.debug_list().entries(self.iter()).finish() 1505 | } 1506 | } 1507 | 1508 | impl fmt::Debug for Drain<'_, K, V> 1509 | where 1510 | K: fmt::Debug, 1511 | V: fmt::Debug, 1512 | { 1513 | #[inline] 1514 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1515 | f.debug_list().entries(self.iter()).finish() 1516 | } 1517 | } 1518 | 1519 | impl<'a, K, V> Iterator for Iter<'a, K, V> { 1520 | type Item = (&'a K, &'a V); 1521 | 1522 | #[inline] 1523 | fn next(&mut self) -> Option<(&'a K, &'a V)> { 1524 | if self.remaining == 0 { 1525 | None 1526 | } else { 1527 | self.remaining -= 1; 1528 | unsafe { 1529 | let (key, value) = (*self.head).entry_ref(); 1530 | self.head = (*self.head).links.value.next.as_ptr(); 1531 | Some((key, value)) 1532 | } 1533 | } 1534 | } 1535 | 1536 | #[inline] 1537 | fn size_hint(&self) -> (usize, Option) { 1538 | (self.remaining, Some(self.remaining)) 1539 | } 1540 | } 1541 | 1542 | impl<'a, K, V> Iterator for IterMut<'a, K, V> { 1543 | type Item = (&'a K, &'a mut V); 1544 | 1545 | #[inline] 1546 | fn next(&mut self) -> Option<(&'a K, &'a mut V)> { 1547 | if self.remaining == 0 { 1548 | None 1549 | } else { 1550 | self.remaining -= 1; 1551 | unsafe { 1552 | let head = self.head.as_ptr(); 1553 | let (key, value) = (*head).entry_mut(); 1554 | self.head = Some((*head).links.value.next); 1555 | Some((key, value)) 1556 | } 1557 | } 1558 | } 1559 | 1560 | #[inline] 1561 | fn size_hint(&self) -> (usize, Option) { 1562 | (self.remaining, Some(self.remaining)) 1563 | } 1564 | } 1565 | 1566 | impl Iterator for IntoIter { 1567 | type Item = (K, V); 1568 | 1569 | #[inline] 1570 | fn next(&mut self) -> Option<(K, V)> { 1571 | if self.remaining == 0 { 1572 | return None; 1573 | } 1574 | self.remaining -= 1; 1575 | unsafe { 1576 | let head = self.head.as_ptr(); 1577 | self.head = Some((*head).links.value.next); 1578 | let mut e = Box::from_raw(head); 1579 | Some(e.take_entry()) 1580 | } 1581 | } 1582 | 1583 | #[inline] 1584 | fn size_hint(&self) -> (usize, Option) { 1585 | (self.remaining, Some(self.remaining)) 1586 | } 1587 | } 1588 | 1589 | impl Iterator for Drain<'_, K, V> { 1590 | type Item = (K, V); 1591 | 1592 | #[inline] 1593 | fn next(&mut self) -> Option<(K, V)> { 1594 | if self.remaining == 0 { 1595 | return None; 1596 | } 1597 | self.remaining -= 1; 1598 | unsafe { 1599 | let mut head = NonNull::new_unchecked(self.head.as_ptr()); 1600 | self.head = Some(head.as_ref().links.value.next); 1601 | let entry = head.as_mut().take_entry(); 1602 | push_free(self.free.as_mut(), head); 1603 | Some(entry) 1604 | } 1605 | } 1606 | 1607 | #[inline] 1608 | fn size_hint(&self) -> (usize, Option) { 1609 | (self.remaining, Some(self.remaining)) 1610 | } 1611 | } 1612 | 1613 | impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> { 1614 | #[inline] 1615 | fn next_back(&mut self) -> Option<(&'a K, &'a V)> { 1616 | if self.remaining == 0 { 1617 | None 1618 | } else { 1619 | self.remaining -= 1; 1620 | unsafe { 1621 | let tail = self.tail; 1622 | self.tail = (*tail).links.value.prev.as_ptr(); 1623 | let (key, value) = (*tail).entry_ref(); 1624 | Some((key, value)) 1625 | } 1626 | } 1627 | } 1628 | } 1629 | 1630 | impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { 1631 | #[inline] 1632 | fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { 1633 | if self.remaining == 0 { 1634 | None 1635 | } else { 1636 | self.remaining -= 1; 1637 | unsafe { 1638 | let tail = self.tail.as_ptr(); 1639 | self.tail = Some((*tail).links.value.prev); 1640 | let (key, value) = (*tail).entry_mut(); 1641 | Some((key, value)) 1642 | } 1643 | } 1644 | } 1645 | } 1646 | 1647 | impl DoubleEndedIterator for IntoIter { 1648 | #[inline] 1649 | fn next_back(&mut self) -> Option<(K, V)> { 1650 | if self.remaining == 0 { 1651 | return None; 1652 | } 1653 | self.remaining -= 1; 1654 | unsafe { 1655 | let mut e = *Box::from_raw(self.tail.as_ptr()); 1656 | self.tail = Some(e.links.value.prev); 1657 | Some(e.take_entry()) 1658 | } 1659 | } 1660 | } 1661 | 1662 | impl DoubleEndedIterator for Drain<'_, K, V> { 1663 | #[inline] 1664 | fn next_back(&mut self) -> Option<(K, V)> { 1665 | if self.remaining == 0 { 1666 | return None; 1667 | } 1668 | self.remaining -= 1; 1669 | unsafe { 1670 | let mut tail = NonNull::new_unchecked(self.tail.as_ptr()); 1671 | self.tail = Some(tail.as_ref().links.value.prev); 1672 | let entry = tail.as_mut().take_entry(); 1673 | push_free(&mut *self.free.as_ptr(), tail); 1674 | Some(entry) 1675 | } 1676 | } 1677 | } 1678 | 1679 | impl ExactSizeIterator for Iter<'_, K, V> {} 1680 | 1681 | impl ExactSizeIterator for IterMut<'_, K, V> {} 1682 | 1683 | impl ExactSizeIterator for IntoIter {} 1684 | 1685 | impl Drop for IntoIter { 1686 | #[inline] 1687 | fn drop(&mut self) { 1688 | for _ in 0..self.remaining { 1689 | unsafe { 1690 | let tail = self.tail.as_ptr(); 1691 | self.tail = Some((*tail).links.value.prev); 1692 | (*tail).take_entry(); 1693 | let _ = Box::from_raw(tail); 1694 | } 1695 | } 1696 | } 1697 | } 1698 | 1699 | impl Drop for Drain<'_, K, V> { 1700 | #[inline] 1701 | fn drop(&mut self) { 1702 | for _ in 0..self.remaining { 1703 | unsafe { 1704 | let mut tail = NonNull::new_unchecked(self.tail.as_ptr()); 1705 | self.tail = Some(tail.as_ref().links.value.prev); 1706 | tail.as_mut().take_entry(); 1707 | push_free(&mut *self.free.as_ptr(), tail); 1708 | } 1709 | } 1710 | } 1711 | } 1712 | 1713 | /// The `CursorMut` struct and its implementation provide the basic mutable Cursor API for Linked 1714 | /// lists as proposed in 1715 | /// [here](https://github.com/rust-lang/rfcs/blob/master/text/2570-linked-list-cursors.md), with 1716 | /// several exceptions: 1717 | /// 1718 | /// - It behaves similarly to Rust's Iterators, returning `None` when the end of the list is 1719 | /// reached. A _guard_ node is positioned between the head and tail of the linked list to 1720 | /// facilitate this. If the cursor is over this guard node, `None` is returned, signaling the end 1721 | /// or start of the list. From this position, the cursor can move in either direction as the 1722 | /// linked list is circular, with the guard node connecting the two ends. 1723 | /// - The current implementation does not include an `index` method, as it does not track the index 1724 | /// of its elements. It provides access to each map entry as a tuple of `(&K, &mut V)`. 1725 | /// 1726 | pub struct CursorMut<'a, K, V, S> { 1727 | cur: *mut Node, 1728 | hash_builder: &'a S, 1729 | free: &'a mut Option>>, 1730 | values: &'a mut Option>>, 1731 | table: &'a mut hashbrown::HashTable>>, 1732 | } 1733 | 1734 | impl CursorMut<'_, K, V, S> { 1735 | /// Returns an `Option` of the current element in the list, provided it is not the 1736 | /// _guard_ node, and `None` overwise. 1737 | #[inline] 1738 | pub fn current(&mut self) -> Option<(&K, &mut V)> { 1739 | unsafe { 1740 | let at = NonNull::new_unchecked(self.cur); 1741 | self.peek(at) 1742 | } 1743 | } 1744 | 1745 | /// Retrieves the next element in the list (moving towards the end). 1746 | #[inline] 1747 | pub fn peek_next(&mut self) -> Option<(&K, &mut V)> { 1748 | unsafe { 1749 | let at = (*self.cur).links.value.next; 1750 | self.peek(at) 1751 | } 1752 | } 1753 | 1754 | /// Retrieves the previous element in the list (moving towards the front). 1755 | #[inline] 1756 | pub fn peek_prev(&mut self) -> Option<(&K, &mut V)> { 1757 | unsafe { 1758 | let at = (*self.cur).links.value.prev; 1759 | self.peek(at) 1760 | } 1761 | } 1762 | 1763 | // Retrieves the element without advancing current position to it. 1764 | #[inline] 1765 | fn peek(&mut self, at: NonNull>) -> Option<(&K, &mut V)> { 1766 | if let Some(values) = self.values { 1767 | unsafe { 1768 | let node = at.as_ptr(); 1769 | if node == values.as_ptr() { 1770 | None 1771 | } else { 1772 | let entry = (*node).entry_mut(); 1773 | Some((&entry.0, &mut entry.1)) 1774 | } 1775 | } 1776 | } else { 1777 | None 1778 | } 1779 | } 1780 | 1781 | /// Updates the pointer to the current element to the next element in the 1782 | /// list (that is, moving towards the end). 1783 | #[inline] 1784 | pub fn move_next(&mut self) { 1785 | let at = unsafe { (*self.cur).links.value.next }; 1786 | self.muv(at); 1787 | } 1788 | 1789 | /// Updates the pointer to the current element to the previous element in the 1790 | /// list (that is, moving towards the front). 1791 | #[inline] 1792 | pub fn move_prev(&mut self) { 1793 | let at = unsafe { (*self.cur).links.value.prev }; 1794 | self.muv(at); 1795 | } 1796 | 1797 | // Updates the pointer to the current element to the one returned by the at closure function. 1798 | #[inline] 1799 | fn muv(&mut self, at: NonNull>) { 1800 | self.cur = at.as_ptr(); 1801 | } 1802 | 1803 | /// Inserts the provided key and value before the current element. It checks if an entry 1804 | /// with the given key exists and, if so, replaces its value with the provided `key` 1805 | /// parameter. The key is not updated; this matters for types that can be `==` without 1806 | /// being identical. 1807 | /// 1808 | /// If the entry doesn't exist, it creates a new one. If a value has been updated, the 1809 | /// function returns the *old* value wrapped with `Some` and `None` otherwise. 1810 | #[inline] 1811 | pub fn insert_before(&mut self, key: K, value: V) -> Option 1812 | where 1813 | K: Eq + Hash, 1814 | S: BuildHasher, 1815 | { 1816 | let before = unsafe { NonNull::new_unchecked(self.cur) }; 1817 | self.insert(key, value, before) 1818 | } 1819 | 1820 | /// Inserts the provided key and value after the current element. It checks if an entry 1821 | /// with the given key exists and, if so, replaces its value with the provided `key` 1822 | /// parameter. The key is not updated; this matters for types that can be `==` without 1823 | /// being identical. 1824 | /// 1825 | /// If the entry doesn't exist, it creates a new one. If a value has been updated, the 1826 | /// function returns the *old* value wrapped with `Some` and `None` otherwise. 1827 | #[inline] 1828 | pub fn insert_after(&mut self, key: K, value: V) -> Option 1829 | where 1830 | K: Eq + Hash, 1831 | S: BuildHasher, 1832 | { 1833 | let before = unsafe { (*self.cur).links.value.next }; 1834 | self.insert(key, value, before) 1835 | } 1836 | 1837 | // Inserts an element immediately before the given `before` node. 1838 | #[inline] 1839 | fn insert(&mut self, key: K, value: V, before: NonNull>) -> Option 1840 | where 1841 | K: Eq + Hash, 1842 | S: BuildHasher, 1843 | { 1844 | unsafe { 1845 | let hash = hash_key(self.hash_builder, &key); 1846 | let i_entry = self 1847 | .table 1848 | .find_entry(hash, |o| (*o).as_ref().key_ref().eq(&key)); 1849 | 1850 | match i_entry { 1851 | Ok(occupied) => { 1852 | let mut node = *occupied.into_mut(); 1853 | let pv = mem::replace(&mut node.as_mut().entry_mut().1, value); 1854 | if node != before { 1855 | detach_node(node); 1856 | attach_before(node, before); 1857 | } 1858 | Some(pv) 1859 | } 1860 | Err(_) => { 1861 | let mut new_node = allocate_node(self.free); 1862 | new_node.as_mut().put_entry((key, value)); 1863 | attach_before(new_node, before); 1864 | let hash_builder = self.hash_builder; 1865 | self.table.insert_unique(hash, new_node, move |k| { 1866 | hash_key(hash_builder, (*k).as_ref().key_ref()) 1867 | }); 1868 | None 1869 | } 1870 | } 1871 | } 1872 | } 1873 | } 1874 | 1875 | pub struct Keys<'a, K, V> { 1876 | inner: Iter<'a, K, V>, 1877 | } 1878 | 1879 | impl fmt::Debug for Keys<'_, K, V> { 1880 | #[inline] 1881 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1882 | f.debug_list().entries(self.clone()).finish() 1883 | } 1884 | } 1885 | 1886 | impl<'a, K, V> Clone for Keys<'a, K, V> { 1887 | #[inline] 1888 | fn clone(&self) -> Keys<'a, K, V> { 1889 | Keys { 1890 | inner: self.inner.clone(), 1891 | } 1892 | } 1893 | } 1894 | 1895 | impl<'a, K, V> Iterator for Keys<'a, K, V> { 1896 | type Item = &'a K; 1897 | 1898 | #[inline] 1899 | fn next(&mut self) -> Option<&'a K> { 1900 | self.inner.next().map(|e| e.0) 1901 | } 1902 | 1903 | #[inline] 1904 | fn size_hint(&self) -> (usize, Option) { 1905 | self.inner.size_hint() 1906 | } 1907 | } 1908 | 1909 | impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { 1910 | #[inline] 1911 | fn next_back(&mut self) -> Option<&'a K> { 1912 | self.inner.next_back().map(|e| e.0) 1913 | } 1914 | } 1915 | 1916 | impl ExactSizeIterator for Keys<'_, K, V> { 1917 | #[inline] 1918 | fn len(&self) -> usize { 1919 | self.inner.len() 1920 | } 1921 | } 1922 | 1923 | pub struct Values<'a, K, V> { 1924 | inner: Iter<'a, K, V>, 1925 | } 1926 | 1927 | impl Clone for Values<'_, K, V> { 1928 | #[inline] 1929 | fn clone(&self) -> Self { 1930 | Values { 1931 | inner: self.inner.clone(), 1932 | } 1933 | } 1934 | } 1935 | 1936 | impl fmt::Debug for Values<'_, K, V> { 1937 | #[inline] 1938 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1939 | f.debug_list().entries(self.clone()).finish() 1940 | } 1941 | } 1942 | 1943 | impl<'a, K, V> Iterator for Values<'a, K, V> { 1944 | type Item = &'a V; 1945 | 1946 | #[inline] 1947 | fn next(&mut self) -> Option<&'a V> { 1948 | self.inner.next().map(|e| e.1) 1949 | } 1950 | 1951 | #[inline] 1952 | fn size_hint(&self) -> (usize, Option) { 1953 | self.inner.size_hint() 1954 | } 1955 | } 1956 | 1957 | impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { 1958 | #[inline] 1959 | fn next_back(&mut self) -> Option<&'a V> { 1960 | self.inner.next_back().map(|e| e.1) 1961 | } 1962 | } 1963 | 1964 | impl ExactSizeIterator for Values<'_, K, V> { 1965 | #[inline] 1966 | fn len(&self) -> usize { 1967 | self.inner.len() 1968 | } 1969 | } 1970 | 1971 | pub struct ValuesMut<'a, K, V> { 1972 | inner: IterMut<'a, K, V>, 1973 | } 1974 | 1975 | impl fmt::Debug for ValuesMut<'_, K, V> 1976 | where 1977 | K: fmt::Debug, 1978 | V: fmt::Debug, 1979 | { 1980 | #[inline] 1981 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1982 | f.debug_list().entries(self.inner.iter()).finish() 1983 | } 1984 | } 1985 | 1986 | impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { 1987 | type Item = &'a mut V; 1988 | 1989 | #[inline] 1990 | fn next(&mut self) -> Option<&'a mut V> { 1991 | self.inner.next().map(|e| e.1) 1992 | } 1993 | 1994 | #[inline] 1995 | fn size_hint(&self) -> (usize, Option) { 1996 | self.inner.size_hint() 1997 | } 1998 | } 1999 | 2000 | impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { 2001 | #[inline] 2002 | fn next_back(&mut self) -> Option<&'a mut V> { 2003 | self.inner.next_back().map(|e| e.1) 2004 | } 2005 | } 2006 | 2007 | impl ExactSizeIterator for ValuesMut<'_, K, V> { 2008 | #[inline] 2009 | fn len(&self) -> usize { 2010 | self.inner.len() 2011 | } 2012 | } 2013 | 2014 | impl<'a, K, V, S> IntoIterator for &'a LinkedHashMap { 2015 | type Item = (&'a K, &'a V); 2016 | type IntoIter = Iter<'a, K, V>; 2017 | 2018 | #[inline] 2019 | fn into_iter(self) -> Iter<'a, K, V> { 2020 | self.iter() 2021 | } 2022 | } 2023 | 2024 | impl<'a, K, V, S> IntoIterator for &'a mut LinkedHashMap { 2025 | type Item = (&'a K, &'a mut V); 2026 | type IntoIter = IterMut<'a, K, V>; 2027 | 2028 | #[inline] 2029 | fn into_iter(self) -> IterMut<'a, K, V> { 2030 | self.iter_mut() 2031 | } 2032 | } 2033 | 2034 | impl IntoIterator for LinkedHashMap { 2035 | type Item = (K, V); 2036 | type IntoIter = IntoIter; 2037 | 2038 | #[inline] 2039 | fn into_iter(mut self) -> IntoIter { 2040 | unsafe { 2041 | let (head, tail) = if let Some(values) = self.values { 2042 | let ValueLinks { 2043 | next: head, 2044 | prev: tail, 2045 | } = values.as_ref().links.value; 2046 | 2047 | let _ = Box::from_raw(self.values.as_ptr()); 2048 | self.values = None; 2049 | 2050 | (Some(head), Some(tail)) 2051 | } else { 2052 | (None, None) 2053 | }; 2054 | let len = self.len(); 2055 | 2056 | drop_free_nodes(self.free.take()); 2057 | 2058 | self.table.clear(); 2059 | 2060 | IntoIter { 2061 | head, 2062 | tail, 2063 | remaining: len, 2064 | marker: PhantomData, 2065 | } 2066 | } 2067 | } 2068 | } 2069 | 2070 | struct ValueLinks { 2071 | next: NonNull>, 2072 | prev: NonNull>, 2073 | } 2074 | 2075 | impl Clone for ValueLinks { 2076 | #[inline] 2077 | fn clone(&self) -> Self { 2078 | *self 2079 | } 2080 | } 2081 | 2082 | impl Copy for ValueLinks {} 2083 | 2084 | struct FreeLink { 2085 | next: Option>>, 2086 | } 2087 | 2088 | impl Clone for FreeLink { 2089 | #[inline] 2090 | fn clone(&self) -> Self { 2091 | *self 2092 | } 2093 | } 2094 | 2095 | impl Copy for FreeLink {} 2096 | 2097 | union Links { 2098 | value: ValueLinks, 2099 | free: FreeLink, 2100 | } 2101 | 2102 | struct Node { 2103 | entry: MaybeUninit<(K, V)>, 2104 | links: Links, 2105 | } 2106 | 2107 | impl Node { 2108 | #[inline] 2109 | unsafe fn put_entry(&mut self, entry: (K, V)) { 2110 | self.entry.as_mut_ptr().write(entry) 2111 | } 2112 | 2113 | #[inline] 2114 | unsafe fn entry_ref(&self) -> &(K, V) { 2115 | &*self.entry.as_ptr() 2116 | } 2117 | 2118 | #[inline] 2119 | unsafe fn key_ref(&self) -> &K { 2120 | &(*self.entry.as_ptr()).0 2121 | } 2122 | 2123 | #[inline] 2124 | unsafe fn entry_mut(&mut self) -> &mut (K, V) { 2125 | &mut *self.entry.as_mut_ptr() 2126 | } 2127 | 2128 | #[inline] 2129 | unsafe fn take_entry(&mut self) -> (K, V) { 2130 | self.entry.as_ptr().read() 2131 | } 2132 | } 2133 | 2134 | trait OptNonNullExt { 2135 | #[allow(clippy::wrong_self_convention)] 2136 | fn as_ptr(self) -> *mut T; 2137 | } 2138 | 2139 | impl OptNonNullExt for Option> { 2140 | #[inline] 2141 | fn as_ptr(self) -> *mut T { 2142 | match self { 2143 | Some(ptr) => ptr.as_ptr(), 2144 | None => ptr::null_mut(), 2145 | } 2146 | } 2147 | } 2148 | 2149 | // Allocate a circular list guard node if not present. 2150 | #[inline] 2151 | unsafe fn ensure_guard_node(head: &mut Option>>) { 2152 | if head.is_none() { 2153 | let mut p = NonNull::new_unchecked(Box::into_raw(Box::new(Node { 2154 | entry: MaybeUninit::uninit(), 2155 | links: Links { 2156 | value: ValueLinks { 2157 | next: NonNull::dangling(), 2158 | prev: NonNull::dangling(), 2159 | }, 2160 | }, 2161 | }))); 2162 | p.as_mut().links.value = ValueLinks { next: p, prev: p }; 2163 | *head = Some(p); 2164 | } 2165 | } 2166 | 2167 | // Attach the `to_attach` node to the existing circular list *before* `node`. 2168 | #[inline] 2169 | unsafe fn attach_before(mut to_attach: NonNull>, mut node: NonNull>) { 2170 | to_attach.as_mut().links.value = ValueLinks { 2171 | prev: node.as_ref().links.value.prev, 2172 | next: node, 2173 | }; 2174 | node.as_mut().links.value.prev = to_attach; 2175 | (*to_attach.as_mut().links.value.prev.as_ptr()) 2176 | .links 2177 | .value 2178 | .next = to_attach; 2179 | } 2180 | 2181 | #[inline] 2182 | unsafe fn detach_node(mut node: NonNull>) { 2183 | node.as_mut().links.value.prev.as_mut().links.value.next = node.as_ref().links.value.next; 2184 | node.as_mut().links.value.next.as_mut().links.value.prev = node.as_ref().links.value.prev; 2185 | } 2186 | 2187 | #[inline] 2188 | unsafe fn push_free( 2189 | free_list: &mut Option>>, 2190 | mut node: NonNull>, 2191 | ) { 2192 | node.as_mut().links.free.next = *free_list; 2193 | *free_list = Some(node); 2194 | } 2195 | 2196 | #[inline] 2197 | unsafe fn pop_free( 2198 | free_list: &mut Option>>, 2199 | ) -> Option>> { 2200 | if let Some(free) = *free_list { 2201 | *free_list = free.as_ref().links.free.next; 2202 | Some(free) 2203 | } else { 2204 | None 2205 | } 2206 | } 2207 | 2208 | #[inline] 2209 | unsafe fn allocate_node(free_list: &mut Option>>) -> NonNull> { 2210 | if let Some(mut free) = pop_free(free_list) { 2211 | free.as_mut().links.value = ValueLinks { 2212 | next: NonNull::dangling(), 2213 | prev: NonNull::dangling(), 2214 | }; 2215 | free 2216 | } else { 2217 | NonNull::new_unchecked(Box::into_raw(Box::new(Node { 2218 | entry: MaybeUninit::uninit(), 2219 | links: Links { 2220 | value: ValueLinks { 2221 | next: NonNull::dangling(), 2222 | prev: NonNull::dangling(), 2223 | }, 2224 | }, 2225 | }))) 2226 | } 2227 | } 2228 | 2229 | // Given node is assumed to be the guard node and is *not* dropped. 2230 | #[inline] 2231 | unsafe fn drop_value_nodes(guard: NonNull>) { 2232 | let mut cur = guard.as_ref().links.value.prev; 2233 | while cur != guard { 2234 | let prev = cur.as_ref().links.value.prev; 2235 | cur.as_mut().take_entry(); 2236 | let _ = Box::from_raw(cur.as_ptr()); 2237 | cur = prev; 2238 | } 2239 | } 2240 | 2241 | // Drops all linked free nodes starting with the given node. Free nodes are only non-circular 2242 | // singly linked, and should have uninitialized keys / values. 2243 | #[inline] 2244 | unsafe fn drop_free_nodes(mut free: Option>>) { 2245 | while let Some(some_free) = free { 2246 | let next_free = some_free.as_ref().links.free.next; 2247 | let _ = Box::from_raw(some_free.as_ptr()); 2248 | free = next_free; 2249 | } 2250 | } 2251 | 2252 | #[inline] 2253 | unsafe fn remove_node( 2254 | free_list: &mut Option>>, 2255 | mut node: NonNull>, 2256 | ) -> (K, V) { 2257 | detach_node(node); 2258 | push_free(free_list, node); 2259 | node.as_mut().take_entry() 2260 | } 2261 | 2262 | #[inline] 2263 | unsafe fn hash_node(s: &S, node: NonNull>) -> u64 2264 | where 2265 | S: BuildHasher, 2266 | K: Hash, 2267 | { 2268 | hash_key(s, node.as_ref().key_ref()) 2269 | } 2270 | 2271 | #[inline] 2272 | fn hash_key(s: &S, k: &Q) -> u64 2273 | where 2274 | S: BuildHasher, 2275 | Q: Hash + ?Sized, 2276 | { 2277 | let mut hasher = s.build_hasher(); 2278 | k.hash(&mut hasher); 2279 | hasher.finish() 2280 | } 2281 | 2282 | // We do not drop the key and value when a value is filtered from the map during the call to 2283 | // `retain`. We need to be very careful not to have a live `HashMap` entry pointing to 2284 | // either a dangling `Node` or a `Node` with dropped keys / values. Since the key and value 2285 | // types may panic on drop, they may short-circuit the entry in the map actually being 2286 | // removed. Instead, we push the removed nodes onto the free list eagerly, then try and 2287 | // drop the keys and values for any newly freed nodes *after* `HashMap::retain` has 2288 | // completely finished. 2289 | struct DropFilteredValues<'a, K, V> { 2290 | free: &'a mut Option>>, 2291 | cur_free: Option>>, 2292 | } 2293 | 2294 | impl DropFilteredValues<'_, K, V> { 2295 | #[inline] 2296 | fn drop_later(&mut self, node: NonNull>) { 2297 | unsafe { 2298 | detach_node(node); 2299 | push_free(&mut self.cur_free, node); 2300 | } 2301 | } 2302 | } 2303 | 2304 | impl Drop for DropFilteredValues<'_, K, V> { 2305 | fn drop(&mut self) { 2306 | unsafe { 2307 | let end_free = self.cur_free; 2308 | while self.cur_free != *self.free { 2309 | let cur_free = self.cur_free.as_ptr(); 2310 | (*cur_free).take_entry(); 2311 | self.cur_free = (*cur_free).links.free.next; 2312 | } 2313 | *self.free = end_free; 2314 | } 2315 | } 2316 | } 2317 | -------------------------------------------------------------------------------- /src/linked_hash_set.rs: -------------------------------------------------------------------------------- 1 | use core::{ 2 | borrow::Borrow, 3 | fmt, 4 | hash::{BuildHasher, Hash, Hasher}, 5 | iter::{Chain, FromIterator}, 6 | ops::{BitAnd, BitOr, BitXor, Sub}, 7 | }; 8 | 9 | use crate::linked_hash_map::{self, LinkedHashMap, TryReserveError}; 10 | use crate::DefaultHashBuilder; 11 | 12 | pub struct LinkedHashSet { 13 | map: LinkedHashMap, 14 | } 15 | 16 | impl LinkedHashSet { 17 | #[inline] 18 | pub fn new() -> LinkedHashSet { 19 | LinkedHashSet { 20 | map: LinkedHashMap::new(), 21 | } 22 | } 23 | 24 | #[inline] 25 | pub fn with_capacity(capacity: usize) -> LinkedHashSet { 26 | LinkedHashSet { 27 | map: LinkedHashMap::with_capacity(capacity), 28 | } 29 | } 30 | } 31 | 32 | impl LinkedHashSet { 33 | #[inline] 34 | pub fn capacity(&self) -> usize { 35 | self.map.capacity() 36 | } 37 | 38 | #[inline] 39 | pub fn iter(&self) -> Iter<'_, T> { 40 | Iter { 41 | iter: self.map.keys(), 42 | } 43 | } 44 | 45 | #[inline] 46 | pub fn len(&self) -> usize { 47 | self.map.len() 48 | } 49 | 50 | #[inline] 51 | pub fn is_empty(&self) -> bool { 52 | self.map.is_empty() 53 | } 54 | 55 | #[inline] 56 | pub fn drain(&mut self) -> Drain { 57 | Drain { 58 | iter: self.map.drain(), 59 | } 60 | } 61 | 62 | #[inline] 63 | pub fn clear(&mut self) { 64 | self.map.clear() 65 | } 66 | 67 | #[inline] 68 | pub fn retain(&mut self, mut f: F) 69 | where 70 | F: FnMut(&T) -> bool, 71 | { 72 | self.map.retain(|k, _| f(k)); 73 | } 74 | } 75 | 76 | impl LinkedHashSet 77 | where 78 | T: Eq + Hash, 79 | S: BuildHasher, 80 | { 81 | #[inline] 82 | pub fn with_hasher(hasher: S) -> LinkedHashSet { 83 | LinkedHashSet { 84 | map: LinkedHashMap::with_hasher(hasher), 85 | } 86 | } 87 | 88 | #[inline] 89 | pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> LinkedHashSet { 90 | LinkedHashSet { 91 | map: LinkedHashMap::with_capacity_and_hasher(capacity, hasher), 92 | } 93 | } 94 | 95 | #[inline] 96 | pub fn hasher(&self) -> &S { 97 | self.map.hasher() 98 | } 99 | 100 | #[inline] 101 | pub fn reserve(&mut self, additional: usize) { 102 | self.map.reserve(additional) 103 | } 104 | 105 | #[inline] 106 | pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { 107 | self.map.try_reserve(additional) 108 | } 109 | 110 | #[inline] 111 | pub fn shrink_to_fit(&mut self) { 112 | self.map.shrink_to_fit() 113 | } 114 | 115 | #[inline] 116 | pub fn difference<'a>(&'a self, other: &'a LinkedHashSet) -> Difference<'a, T, S> { 117 | Difference { 118 | iter: self.iter(), 119 | other, 120 | } 121 | } 122 | 123 | #[inline] 124 | pub fn symmetric_difference<'a>( 125 | &'a self, 126 | other: &'a LinkedHashSet, 127 | ) -> SymmetricDifference<'a, T, S> { 128 | SymmetricDifference { 129 | iter: self.difference(other).chain(other.difference(self)), 130 | } 131 | } 132 | 133 | #[inline] 134 | pub fn intersection<'a>(&'a self, other: &'a LinkedHashSet) -> Intersection<'a, T, S> { 135 | Intersection { 136 | iter: self.iter(), 137 | other, 138 | } 139 | } 140 | 141 | #[inline] 142 | pub fn union<'a>(&'a self, other: &'a LinkedHashSet) -> Union<'a, T, S> { 143 | Union { 144 | iter: self.iter().chain(other.difference(self)), 145 | } 146 | } 147 | 148 | #[inline] 149 | pub fn contains(&self, value: &Q) -> bool 150 | where 151 | T: Borrow, 152 | Q: Hash + Eq + ?Sized, 153 | { 154 | self.map.contains_key(value) 155 | } 156 | 157 | #[inline] 158 | pub fn get(&self, value: &Q) -> Option<&T> 159 | where 160 | T: Borrow, 161 | Q: Hash + Eq + ?Sized, 162 | { 163 | self.map.raw_entry().from_key(value).map(|p| p.0) 164 | } 165 | 166 | #[inline] 167 | pub fn get_or_insert(&mut self, value: T) -> &T { 168 | self.map 169 | .raw_entry_mut() 170 | .from_key(&value) 171 | .or_insert(value, ()) 172 | .0 173 | } 174 | 175 | #[inline] 176 | pub fn get_or_insert_with(&mut self, value: &Q, f: F) -> &T 177 | where 178 | T: Borrow, 179 | Q: Hash + Eq + ?Sized, 180 | F: FnOnce(&Q) -> T, 181 | { 182 | self.map 183 | .raw_entry_mut() 184 | .from_key(value) 185 | .or_insert_with(|| (f(value), ())) 186 | .0 187 | } 188 | 189 | #[inline] 190 | pub fn is_disjoint(&self, other: &LinkedHashSet) -> bool { 191 | self.iter().all(|v| !other.contains(v)) 192 | } 193 | 194 | #[inline] 195 | pub fn is_subset(&self, other: &LinkedHashSet) -> bool { 196 | self.iter().all(|v| other.contains(v)) 197 | } 198 | 199 | #[inline] 200 | pub fn is_superset(&self, other: &LinkedHashSet) -> bool { 201 | other.is_subset(self) 202 | } 203 | 204 | /// Inserts the given value into the set. 205 | /// 206 | /// If the set did not have this value present, inserts it at the *back* of the internal linked 207 | /// list and returns true, otherwise it moves the existing value to the *back* of the internal 208 | /// linked list and returns false. 209 | #[inline] 210 | pub fn insert(&mut self, value: T) -> bool { 211 | self.map.insert(value, ()).is_none() 212 | } 213 | 214 | /// Adds the given value to the set, replacing the existing value. 215 | /// 216 | /// If a previous value existed, returns the replaced value. In this case, the value's position 217 | /// in the internal linked list is *not* changed. 218 | #[inline] 219 | pub fn replace(&mut self, value: T) -> Option { 220 | match self.map.entry(value) { 221 | linked_hash_map::Entry::Occupied(occupied) => Some(occupied.replace_key()), 222 | linked_hash_map::Entry::Vacant(vacant) => { 223 | vacant.insert(()); 224 | None 225 | } 226 | } 227 | } 228 | 229 | #[inline] 230 | pub fn remove(&mut self, value: &Q) -> bool 231 | where 232 | T: Borrow, 233 | Q: Hash + Eq + ?Sized, 234 | { 235 | self.map.remove(value).is_some() 236 | } 237 | 238 | #[inline] 239 | pub fn take(&mut self, value: &Q) -> Option 240 | where 241 | T: Borrow, 242 | Q: Hash + Eq + ?Sized, 243 | { 244 | match self.map.raw_entry_mut().from_key(value) { 245 | linked_hash_map::RawEntryMut::Occupied(occupied) => Some(occupied.remove_entry().0), 246 | linked_hash_map::RawEntryMut::Vacant(_) => None, 247 | } 248 | } 249 | 250 | #[inline] 251 | pub fn front(&self) -> Option<&T> { 252 | self.map.front().map(|(k, _)| k) 253 | } 254 | 255 | #[inline] 256 | pub fn pop_front(&mut self) -> Option { 257 | self.map.pop_front().map(|(k, _)| k) 258 | } 259 | 260 | #[inline] 261 | pub fn back(&self) -> Option<&T> { 262 | self.map.back().map(|(k, _)| k) 263 | } 264 | 265 | #[inline] 266 | pub fn pop_back(&mut self) -> Option { 267 | self.map.pop_back().map(|(k, _)| k) 268 | } 269 | 270 | #[inline] 271 | pub fn to_front(&mut self, value: &Q) -> bool 272 | where 273 | T: Borrow, 274 | Q: Hash + Eq + ?Sized, 275 | { 276 | match self.map.raw_entry_mut().from_key(value) { 277 | linked_hash_map::RawEntryMut::Occupied(mut occupied) => { 278 | occupied.to_front(); 279 | true 280 | } 281 | linked_hash_map::RawEntryMut::Vacant(_) => false, 282 | } 283 | } 284 | 285 | #[inline] 286 | pub fn to_back(&mut self, value: &Q) -> bool 287 | where 288 | T: Borrow, 289 | Q: Hash + Eq + ?Sized, 290 | { 291 | match self.map.raw_entry_mut().from_key(value) { 292 | linked_hash_map::RawEntryMut::Occupied(mut occupied) => { 293 | occupied.to_back(); 294 | true 295 | } 296 | linked_hash_map::RawEntryMut::Vacant(_) => false, 297 | } 298 | } 299 | 300 | #[inline] 301 | pub fn retain_with_order(&mut self, mut f: F) 302 | where 303 | F: FnMut(&T) -> bool, 304 | { 305 | self.map.retain_with_order(|k, _| f(k)); 306 | } 307 | } 308 | 309 | impl Clone for LinkedHashSet { 310 | #[inline] 311 | fn clone(&self) -> Self { 312 | let map = self.map.clone(); 313 | Self { map } 314 | } 315 | } 316 | 317 | impl PartialEq for LinkedHashSet 318 | where 319 | T: Eq + Hash, 320 | S: BuildHasher, 321 | { 322 | #[inline] 323 | fn eq(&self, other: &Self) -> bool { 324 | self.len() == other.len() && self.iter().eq(other) 325 | } 326 | } 327 | 328 | impl Hash for LinkedHashSet 329 | where 330 | T: Eq + Hash, 331 | S: BuildHasher, 332 | { 333 | #[inline] 334 | fn hash(&self, state: &mut H) { 335 | for e in self { 336 | e.hash(state); 337 | } 338 | } 339 | } 340 | 341 | impl Eq for LinkedHashSet 342 | where 343 | T: Eq + Hash, 344 | S: BuildHasher, 345 | { 346 | } 347 | 348 | impl fmt::Debug for LinkedHashSet 349 | where 350 | T: fmt::Debug, 351 | { 352 | #[inline] 353 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 354 | f.debug_set().entries(self.iter()).finish() 355 | } 356 | } 357 | 358 | impl FromIterator for LinkedHashSet 359 | where 360 | T: Eq + Hash, 361 | S: BuildHasher + Default, 362 | { 363 | #[inline] 364 | fn from_iter>(iter: I) -> LinkedHashSet { 365 | let mut set = LinkedHashSet::with_hasher(Default::default()); 366 | set.extend(iter); 367 | set 368 | } 369 | } 370 | 371 | impl Extend for LinkedHashSet 372 | where 373 | T: Eq + Hash, 374 | S: BuildHasher, 375 | { 376 | #[inline] 377 | fn extend>(&mut self, iter: I) { 378 | self.map.extend(iter.into_iter().map(|k| (k, ()))); 379 | } 380 | } 381 | 382 | impl<'a, T, S> Extend<&'a T> for LinkedHashSet 383 | where 384 | T: 'a + Eq + Hash + Copy, 385 | S: BuildHasher, 386 | { 387 | #[inline] 388 | fn extend>(&mut self, iter: I) { 389 | self.extend(iter.into_iter().cloned()); 390 | } 391 | } 392 | 393 | impl Default for LinkedHashSet 394 | where 395 | S: Default, 396 | { 397 | #[inline] 398 | fn default() -> LinkedHashSet { 399 | LinkedHashSet { 400 | map: LinkedHashMap::default(), 401 | } 402 | } 403 | } 404 | 405 | impl BitOr<&LinkedHashSet> for &LinkedHashSet 406 | where 407 | T: Eq + Hash + Clone, 408 | S: BuildHasher + Default, 409 | { 410 | type Output = LinkedHashSet; 411 | 412 | #[inline] 413 | fn bitor(self, rhs: &LinkedHashSet) -> LinkedHashSet { 414 | self.union(rhs).cloned().collect() 415 | } 416 | } 417 | 418 | impl BitAnd<&LinkedHashSet> for &LinkedHashSet 419 | where 420 | T: Eq + Hash + Clone, 421 | S: BuildHasher + Default, 422 | { 423 | type Output = LinkedHashSet; 424 | 425 | #[inline] 426 | fn bitand(self, rhs: &LinkedHashSet) -> LinkedHashSet { 427 | self.intersection(rhs).cloned().collect() 428 | } 429 | } 430 | 431 | impl BitXor<&LinkedHashSet> for &LinkedHashSet 432 | where 433 | T: Eq + Hash + Clone, 434 | S: BuildHasher + Default, 435 | { 436 | type Output = LinkedHashSet; 437 | 438 | #[inline] 439 | fn bitxor(self, rhs: &LinkedHashSet) -> LinkedHashSet { 440 | self.symmetric_difference(rhs).cloned().collect() 441 | } 442 | } 443 | 444 | impl Sub<&LinkedHashSet> for &LinkedHashSet 445 | where 446 | T: Eq + Hash + Clone, 447 | S: BuildHasher + Default, 448 | { 449 | type Output = LinkedHashSet; 450 | 451 | #[inline] 452 | fn sub(self, rhs: &LinkedHashSet) -> LinkedHashSet { 453 | self.difference(rhs).cloned().collect() 454 | } 455 | } 456 | 457 | pub struct Iter<'a, K> { 458 | iter: linked_hash_map::Keys<'a, K, ()>, 459 | } 460 | 461 | pub struct IntoIter { 462 | iter: linked_hash_map::IntoIter, 463 | } 464 | 465 | pub struct Drain<'a, K: 'a> { 466 | iter: linked_hash_map::Drain<'a, K, ()>, 467 | } 468 | 469 | pub struct Intersection<'a, T, S> { 470 | iter: Iter<'a, T>, 471 | other: &'a LinkedHashSet, 472 | } 473 | 474 | pub struct Difference<'a, T, S> { 475 | iter: Iter<'a, T>, 476 | other: &'a LinkedHashSet, 477 | } 478 | 479 | pub struct SymmetricDifference<'a, T, S> { 480 | iter: Chain, Difference<'a, T, S>>, 481 | } 482 | 483 | pub struct Union<'a, T, S> { 484 | iter: Chain, Difference<'a, T, S>>, 485 | } 486 | 487 | impl<'a, T, S> IntoIterator for &'a LinkedHashSet { 488 | type Item = &'a T; 489 | type IntoIter = Iter<'a, T>; 490 | 491 | #[inline] 492 | fn into_iter(self) -> Iter<'a, T> { 493 | self.iter() 494 | } 495 | } 496 | 497 | impl IntoIterator for LinkedHashSet { 498 | type Item = T; 499 | type IntoIter = IntoIter; 500 | 501 | #[inline] 502 | fn into_iter(self) -> IntoIter { 503 | IntoIter { 504 | iter: self.map.into_iter(), 505 | } 506 | } 507 | } 508 | 509 | impl<'a, K> Clone for Iter<'a, K> { 510 | #[inline] 511 | fn clone(&self) -> Iter<'a, K> { 512 | Iter { 513 | iter: self.iter.clone(), 514 | } 515 | } 516 | } 517 | impl<'a, K> Iterator for Iter<'a, K> { 518 | type Item = &'a K; 519 | 520 | #[inline] 521 | fn next(&mut self) -> Option<&'a K> { 522 | self.iter.next() 523 | } 524 | 525 | #[inline] 526 | fn size_hint(&self) -> (usize, Option) { 527 | self.iter.size_hint() 528 | } 529 | } 530 | 531 | impl ExactSizeIterator for Iter<'_, K> {} 532 | 533 | impl<'a, T> DoubleEndedIterator for Iter<'a, T> { 534 | #[inline] 535 | fn next_back(&mut self) -> Option<&'a T> { 536 | self.iter.next_back() 537 | } 538 | } 539 | 540 | impl fmt::Debug for Iter<'_, K> { 541 | #[inline] 542 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 543 | f.debug_list().entries(self.clone()).finish() 544 | } 545 | } 546 | 547 | impl Iterator for IntoIter { 548 | type Item = K; 549 | 550 | #[inline] 551 | fn next(&mut self) -> Option { 552 | self.iter.next().map(|(k, _)| k) 553 | } 554 | 555 | #[inline] 556 | fn size_hint(&self) -> (usize, Option) { 557 | self.iter.size_hint() 558 | } 559 | } 560 | 561 | impl ExactSizeIterator for IntoIter {} 562 | 563 | impl DoubleEndedIterator for IntoIter { 564 | #[inline] 565 | fn next_back(&mut self) -> Option { 566 | self.iter.next_back().map(|(k, _)| k) 567 | } 568 | } 569 | 570 | impl Iterator for Drain<'_, K> { 571 | type Item = K; 572 | 573 | #[inline] 574 | fn next(&mut self) -> Option { 575 | self.iter.next().map(|(k, _)| k) 576 | } 577 | 578 | #[inline] 579 | fn size_hint(&self) -> (usize, Option) { 580 | self.iter.size_hint() 581 | } 582 | } 583 | 584 | impl DoubleEndedIterator for Drain<'_, K> { 585 | #[inline] 586 | fn next_back(&mut self) -> Option { 587 | self.iter.next_back().map(|(k, _)| k) 588 | } 589 | } 590 | 591 | impl ExactSizeIterator for Drain<'_, K> {} 592 | 593 | impl<'a, T, S> Clone for Intersection<'a, T, S> { 594 | #[inline] 595 | fn clone(&self) -> Intersection<'a, T, S> { 596 | Intersection { 597 | iter: self.iter.clone(), 598 | ..*self 599 | } 600 | } 601 | } 602 | 603 | impl<'a, T, S> Iterator for Intersection<'a, T, S> 604 | where 605 | T: Eq + Hash, 606 | S: BuildHasher, 607 | { 608 | type Item = &'a T; 609 | 610 | #[inline] 611 | fn next(&mut self) -> Option<&'a T> { 612 | loop { 613 | match self.iter.next() { 614 | None => return None, 615 | Some(elt) => { 616 | if self.other.contains(elt) { 617 | return Some(elt); 618 | } 619 | } 620 | } 621 | } 622 | } 623 | 624 | #[inline] 625 | fn size_hint(&self) -> (usize, Option) { 626 | let (_, upper) = self.iter.size_hint(); 627 | (0, upper) 628 | } 629 | } 630 | 631 | impl fmt::Debug for Intersection<'_, T, S> 632 | where 633 | T: fmt::Debug + Eq + Hash, 634 | S: BuildHasher, 635 | { 636 | #[inline] 637 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 638 | f.debug_list().entries(self.clone()).finish() 639 | } 640 | } 641 | 642 | impl<'a, T, S> Clone for Difference<'a, T, S> { 643 | #[inline] 644 | fn clone(&self) -> Difference<'a, T, S> { 645 | Difference { 646 | iter: self.iter.clone(), 647 | ..*self 648 | } 649 | } 650 | } 651 | 652 | impl<'a, T, S> Iterator for Difference<'a, T, S> 653 | where 654 | T: Eq + Hash, 655 | S: BuildHasher, 656 | { 657 | type Item = &'a T; 658 | 659 | #[inline] 660 | fn next(&mut self) -> Option<&'a T> { 661 | loop { 662 | match self.iter.next() { 663 | None => return None, 664 | Some(elt) => { 665 | if !self.other.contains(elt) { 666 | return Some(elt); 667 | } 668 | } 669 | } 670 | } 671 | } 672 | 673 | #[inline] 674 | fn size_hint(&self) -> (usize, Option) { 675 | let (_, upper) = self.iter.size_hint(); 676 | (0, upper) 677 | } 678 | } 679 | 680 | impl fmt::Debug for Difference<'_, T, S> 681 | where 682 | T: fmt::Debug + Eq + Hash, 683 | S: BuildHasher, 684 | { 685 | #[inline] 686 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 687 | f.debug_list().entries(self.clone()).finish() 688 | } 689 | } 690 | 691 | impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> { 692 | #[inline] 693 | fn clone(&self) -> SymmetricDifference<'a, T, S> { 694 | SymmetricDifference { 695 | iter: self.iter.clone(), 696 | } 697 | } 698 | } 699 | 700 | impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> 701 | where 702 | T: Eq + Hash, 703 | S: BuildHasher, 704 | { 705 | type Item = &'a T; 706 | 707 | #[inline] 708 | fn next(&mut self) -> Option<&'a T> { 709 | self.iter.next() 710 | } 711 | 712 | #[inline] 713 | fn size_hint(&self) -> (usize, Option) { 714 | self.iter.size_hint() 715 | } 716 | } 717 | 718 | impl fmt::Debug for SymmetricDifference<'_, T, S> 719 | where 720 | T: fmt::Debug + Eq + Hash, 721 | S: BuildHasher, 722 | { 723 | #[inline] 724 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 725 | f.debug_list().entries(self.clone()).finish() 726 | } 727 | } 728 | 729 | impl<'a, T, S> Clone for Union<'a, T, S> { 730 | #[inline] 731 | fn clone(&self) -> Union<'a, T, S> { 732 | Union { 733 | iter: self.iter.clone(), 734 | } 735 | } 736 | } 737 | 738 | impl fmt::Debug for Union<'_, T, S> 739 | where 740 | T: fmt::Debug + Eq + Hash, 741 | S: BuildHasher, 742 | { 743 | #[inline] 744 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 745 | f.debug_list().entries(self.clone()).finish() 746 | } 747 | } 748 | 749 | impl<'a, T, S> Iterator for Union<'a, T, S> 750 | where 751 | T: Eq + Hash, 752 | S: BuildHasher, 753 | { 754 | type Item = &'a T; 755 | 756 | #[inline] 757 | fn next(&mut self) -> Option<&'a T> { 758 | self.iter.next() 759 | } 760 | 761 | #[inline] 762 | fn size_hint(&self) -> (usize, Option) { 763 | self.iter.size_hint() 764 | } 765 | } 766 | -------------------------------------------------------------------------------- /src/lru_cache.rs: -------------------------------------------------------------------------------- 1 | use core::{ 2 | borrow::Borrow, 3 | fmt, 4 | hash::{BuildHasher, Hash}, 5 | }; 6 | 7 | use crate::linked_hash_map::{self, LinkedHashMap}; 8 | use crate::DefaultHashBuilder; 9 | 10 | pub use crate::linked_hash_map::{ 11 | Drain, Entry, IntoIter, Iter, IterMut, OccupiedEntry, RawEntryBuilder, RawEntryBuilderMut, 12 | RawOccupiedEntryMut, RawVacantEntryMut, VacantEntry, 13 | }; 14 | 15 | pub struct LruCache { 16 | map: LinkedHashMap, 17 | max_size: usize, 18 | } 19 | 20 | impl LruCache { 21 | #[inline] 22 | pub fn new(capacity: usize) -> Self { 23 | LruCache { 24 | map: LinkedHashMap::new(), 25 | max_size: capacity, 26 | } 27 | } 28 | 29 | /// Create a new unbounded `LruCache` that does not automatically evict entries. 30 | /// 31 | /// A simple convenience method that is equivalent to `LruCache::new(usize::MAX)` 32 | #[inline] 33 | pub fn new_unbounded() -> Self { 34 | LruCache::new(usize::MAX) 35 | } 36 | } 37 | 38 | impl LruCache { 39 | #[inline] 40 | pub fn with_hasher(capacity: usize, hash_builder: S) -> Self { 41 | LruCache { 42 | map: LinkedHashMap::with_hasher(hash_builder), 43 | max_size: capacity, 44 | } 45 | } 46 | 47 | #[inline] 48 | pub fn capacity(&self) -> usize { 49 | self.max_size 50 | } 51 | 52 | #[inline] 53 | pub fn len(&self) -> usize { 54 | self.map.len() 55 | } 56 | 57 | #[inline] 58 | pub fn is_empty(&self) -> bool { 59 | self.map.is_empty() 60 | } 61 | 62 | #[inline] 63 | pub fn clear(&mut self) { 64 | self.map.clear(); 65 | } 66 | 67 | #[inline] 68 | pub fn iter(&self) -> Iter { 69 | self.map.iter() 70 | } 71 | 72 | #[inline] 73 | pub fn iter_mut(&mut self) -> IterMut { 74 | self.map.iter_mut() 75 | } 76 | 77 | #[inline] 78 | pub fn drain(&mut self) -> Drain { 79 | self.map.drain() 80 | } 81 | 82 | #[inline] 83 | pub fn retain(&mut self, f: F) 84 | where 85 | F: FnMut(&K, &mut V) -> bool, 86 | { 87 | self.map.retain(f); 88 | } 89 | } 90 | 91 | impl LruCache 92 | where 93 | S: BuildHasher, 94 | { 95 | #[inline] 96 | pub fn contains_key(&self, key: &Q) -> bool 97 | where 98 | K: Borrow, 99 | Q: Hash + Eq + ?Sized, 100 | { 101 | self.map.contains_key(key) 102 | } 103 | 104 | /// Insert a new value into the `LruCache`. 105 | /// 106 | /// If necessary, will remove the value at the front of the LRU list to make room. 107 | #[inline] 108 | pub fn insert(&mut self, k: K, v: V) -> Option { 109 | let old_val = self.map.insert(k, v); 110 | if self.len() > self.capacity() { 111 | self.remove_lru(); 112 | } 113 | old_val 114 | } 115 | 116 | /// Get the value for the given key, *without* marking the value as recently used and moving it 117 | /// to the back of the LRU list. 118 | #[inline] 119 | pub fn peek(&self, k: &Q) -> Option<&V> 120 | where 121 | K: Borrow, 122 | Q: Hash + Eq + ?Sized, 123 | { 124 | self.map.get(k) 125 | } 126 | 127 | /// Get the value for the given key mutably, *without* marking the value as recently used and 128 | /// moving it to the back of the LRU list. 129 | #[inline] 130 | pub fn peek_mut(&mut self, k: &Q) -> Option<&mut V> 131 | where 132 | K: Borrow, 133 | Q: Hash + Eq + ?Sized, 134 | { 135 | self.map.get_mut(k) 136 | } 137 | 138 | /// Retrieve the given key, marking it as recently used and moving it to the back of the LRU 139 | /// list. 140 | #[inline] 141 | pub fn get(&mut self, k: &Q) -> Option<&V> 142 | where 143 | K: Borrow, 144 | Q: Hash + Eq + ?Sized, 145 | { 146 | self.get_mut(k).map(|v| &*v) 147 | } 148 | 149 | /// Retrieve the given key, marking it as recently used and moving it to the back of the LRU 150 | /// list. 151 | #[inline] 152 | pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> 153 | where 154 | K: Borrow, 155 | Q: Hash + Eq + ?Sized, 156 | { 157 | match self.map.raw_entry_mut().from_key(k) { 158 | linked_hash_map::RawEntryMut::Occupied(mut occupied) => { 159 | occupied.to_back(); 160 | Some(occupied.into_mut()) 161 | } 162 | linked_hash_map::RawEntryMut::Vacant(_) => None, 163 | } 164 | } 165 | 166 | /// If the returned entry is vacant, it will always have room to insert a single value. By 167 | /// using the entry API, you can exceed the configured capacity by 1. 168 | /// 169 | /// The returned entry is not automatically moved to the back of the LRU list. By calling 170 | /// `Entry::to_back` / `Entry::to_front` you can manually control the position of this entry in 171 | /// the LRU list. 172 | #[inline] 173 | pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> { 174 | if self.len() > self.capacity() { 175 | self.remove_lru(); 176 | } 177 | self.map.entry(key) 178 | } 179 | 180 | /// The constructed raw entry is never automatically moved to the back of the LRU list. By 181 | /// calling `Entry::to_back` / `Entry::to_front` you can manually control the position of this 182 | /// entry in the LRU list. 183 | #[inline] 184 | pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S> { 185 | self.map.raw_entry() 186 | } 187 | 188 | /// If the constructed raw entry is vacant, it will always have room to insert a single value. 189 | /// By using the raw entry API, you can exceed the configured capacity by 1. 190 | /// 191 | /// The constructed raw entry is never automatically moved to the back of the LRU list. By 192 | /// calling `Entry::to_back` / `Entry::to_front` you can manually control the position of this 193 | /// entry in the LRU list. 194 | #[inline] 195 | pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { 196 | if self.len() > self.capacity() { 197 | self.remove_lru(); 198 | } 199 | self.map.raw_entry_mut() 200 | } 201 | 202 | #[inline] 203 | pub fn remove(&mut self, k: &Q) -> Option 204 | where 205 | K: Borrow, 206 | Q: Hash + Eq + ?Sized, 207 | { 208 | self.map.remove(k) 209 | } 210 | 211 | #[inline] 212 | pub fn remove_entry(&mut self, k: &Q) -> Option<(K, V)> 213 | where 214 | K: Borrow, 215 | Q: Hash + Eq + ?Sized, 216 | { 217 | self.map.remove_entry(k) 218 | } 219 | 220 | /// Set the new cache capacity for the `LruCache`. 221 | /// 222 | /// If there are more entries in the `LruCache` than the new capacity will allow, they are 223 | /// removed. 224 | #[inline] 225 | pub fn set_capacity(&mut self, capacity: usize) { 226 | for _ in capacity..self.len() { 227 | self.remove_lru(); 228 | } 229 | self.max_size = capacity; 230 | } 231 | 232 | /// Remove the least recently used entry and return it. 233 | /// 234 | /// If the `LruCache` is empty this will return None. 235 | #[inline] 236 | pub fn remove_lru(&mut self) -> Option<(K, V)> { 237 | self.map.pop_front() 238 | } 239 | } 240 | 241 | impl Clone for LruCache { 242 | #[inline] 243 | fn clone(&self) -> Self { 244 | LruCache { 245 | map: self.map.clone(), 246 | max_size: self.max_size, 247 | } 248 | } 249 | } 250 | 251 | impl Extend<(K, V)> for LruCache { 252 | #[inline] 253 | fn extend>(&mut self, iter: I) { 254 | for (k, v) in iter { 255 | self.insert(k, v); 256 | } 257 | } 258 | } 259 | 260 | impl IntoIterator for LruCache { 261 | type Item = (K, V); 262 | type IntoIter = IntoIter; 263 | 264 | #[inline] 265 | fn into_iter(self) -> IntoIter { 266 | self.map.into_iter() 267 | } 268 | } 269 | 270 | impl<'a, K, V, S> IntoIterator for &'a LruCache { 271 | type Item = (&'a K, &'a V); 272 | type IntoIter = Iter<'a, K, V>; 273 | 274 | #[inline] 275 | fn into_iter(self) -> Iter<'a, K, V> { 276 | self.iter() 277 | } 278 | } 279 | 280 | impl<'a, K, V, S> IntoIterator for &'a mut LruCache { 281 | type Item = (&'a K, &'a mut V); 282 | type IntoIter = IterMut<'a, K, V>; 283 | 284 | #[inline] 285 | fn into_iter(self) -> IterMut<'a, K, V> { 286 | self.iter_mut() 287 | } 288 | } 289 | 290 | impl fmt::Debug for LruCache 291 | where 292 | K: fmt::Debug, 293 | V: fmt::Debug, 294 | { 295 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 296 | f.debug_map().entries(self.iter().rev()).finish() 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /src/serde.rs: -------------------------------------------------------------------------------- 1 | use core::{ 2 | fmt::{self, Formatter}, 3 | hash::{BuildHasher, Hash}, 4 | marker::PhantomData, 5 | }; 6 | 7 | use serde::{ 8 | de::{MapAccess, SeqAccess, Visitor}, 9 | ser::{SerializeMap, SerializeSeq}, 10 | Deserialize, Deserializer, Serialize, Serializer, 11 | }; 12 | 13 | use crate::{LinkedHashMap, LinkedHashSet}; 14 | 15 | // LinkedHashMap impls 16 | 17 | impl Serialize for LinkedHashMap 18 | where 19 | K: Serialize + Eq + Hash, 20 | V: Serialize, 21 | S: BuildHasher, 22 | { 23 | #[inline] 24 | fn serialize(&self, serializer: T) -> Result { 25 | let mut map_serializer = serializer.serialize_map(Some(self.len()))?; 26 | for (k, v) in self { 27 | map_serializer.serialize_key(k)?; 28 | map_serializer.serialize_value(v)?; 29 | } 30 | map_serializer.end() 31 | } 32 | } 33 | 34 | impl<'de, K, V, S> Deserialize<'de> for LinkedHashMap 35 | where 36 | K: Deserialize<'de> + Eq + Hash, 37 | V: Deserialize<'de>, 38 | S: BuildHasher + Default, 39 | { 40 | fn deserialize>(deserializer: D) -> Result { 41 | #[derive(Debug)] 42 | pub struct LinkedHashMapVisitor { 43 | marker: PhantomData>, 44 | } 45 | 46 | impl LinkedHashMapVisitor { 47 | fn new() -> Self { 48 | LinkedHashMapVisitor { 49 | marker: PhantomData, 50 | } 51 | } 52 | } 53 | 54 | impl Default for LinkedHashMapVisitor { 55 | fn default() -> Self { 56 | Self::new() 57 | } 58 | } 59 | 60 | impl<'de, K, V, S> Visitor<'de> for LinkedHashMapVisitor 61 | where 62 | K: Deserialize<'de> + Eq + Hash, 63 | V: Deserialize<'de>, 64 | S: BuildHasher + Default, 65 | { 66 | type Value = LinkedHashMap; 67 | 68 | fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { 69 | write!(formatter, "a map") 70 | } 71 | 72 | #[inline] 73 | fn visit_map>(self, mut map: M) -> Result { 74 | let mut values = LinkedHashMap::with_capacity_and_hasher( 75 | map.size_hint().unwrap_or(0), 76 | S::default(), 77 | ); 78 | 79 | while let Some((k, v)) = map.next_entry()? { 80 | values.insert(k, v); 81 | } 82 | 83 | Ok(values) 84 | } 85 | } 86 | 87 | deserializer.deserialize_map(LinkedHashMapVisitor::default()) 88 | } 89 | } 90 | 91 | // LinkedHashSet impls 92 | 93 | impl Serialize for LinkedHashSet 94 | where 95 | T: Serialize + Eq + Hash, 96 | S: BuildHasher, 97 | { 98 | #[inline] 99 | fn serialize(&self, serializer: U) -> Result { 100 | let mut seq_serializer = serializer.serialize_seq(Some(self.len()))?; 101 | for v in self { 102 | seq_serializer.serialize_element(v)?; 103 | } 104 | seq_serializer.end() 105 | } 106 | } 107 | 108 | impl<'de, T, S> Deserialize<'de> for LinkedHashSet 109 | where 110 | T: Deserialize<'de> + Eq + Hash, 111 | S: BuildHasher + Default, 112 | { 113 | fn deserialize>(deserializer: D) -> Result { 114 | #[derive(Debug)] 115 | pub struct LinkedHashSetVisitor { 116 | marker: PhantomData>, 117 | } 118 | 119 | impl LinkedHashSetVisitor { 120 | fn new() -> Self { 121 | LinkedHashSetVisitor { 122 | marker: PhantomData, 123 | } 124 | } 125 | } 126 | 127 | impl Default for LinkedHashSetVisitor { 128 | fn default() -> Self { 129 | Self::new() 130 | } 131 | } 132 | 133 | impl<'de, T, S> Visitor<'de> for LinkedHashSetVisitor 134 | where 135 | T: Deserialize<'de> + Eq + Hash, 136 | S: BuildHasher + Default, 137 | { 138 | type Value = LinkedHashSet; 139 | 140 | fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { 141 | write!(formatter, "a sequence") 142 | } 143 | 144 | #[inline] 145 | fn visit_seq>(self, mut seq: SA) -> Result { 146 | let mut values = LinkedHashSet::with_capacity_and_hasher( 147 | seq.size_hint().unwrap_or(0), 148 | S::default(), 149 | ); 150 | 151 | while let Some(v) = seq.next_element()? { 152 | values.insert(v); 153 | } 154 | 155 | Ok(values) 156 | } 157 | } 158 | 159 | deserializer.deserialize_seq(LinkedHashSetVisitor::default()) 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /tests/linked_hash_map.rs: -------------------------------------------------------------------------------- 1 | use hashlink::{linked_hash_map, LinkedHashMap}; 2 | 3 | #[allow(dead_code)] 4 | fn assert_covariance() { 5 | fn set<'new>(v: LinkedHashMap<&'static str, ()>) -> LinkedHashMap<&'new str, ()> { 6 | v 7 | } 8 | 9 | fn iter<'a, 'new>( 10 | v: linked_hash_map::Iter<'a, &'static str, &'static str>, 11 | ) -> linked_hash_map::Iter<'a, &'new str, &'new str> { 12 | v 13 | } 14 | 15 | fn iter_mut<'a, 'new>( 16 | v: linked_hash_map::Iter<'a, &'static str, ()>, 17 | ) -> linked_hash_map::Iter<'a, &'new str, ()> { 18 | v 19 | } 20 | 21 | fn into_iter<'new>( 22 | v: linked_hash_map::IntoIter<&'static str, &'static str>, 23 | ) -> linked_hash_map::IntoIter<&'new str, &'new str> { 24 | v 25 | } 26 | 27 | fn drain<'new>( 28 | d: linked_hash_map::Drain<'static, &'static str, &'static str>, 29 | ) -> linked_hash_map::Drain<'new, &'new str, &'new str> { 30 | d 31 | } 32 | 33 | fn raw_entry_builder<'a, 'new>( 34 | v: linked_hash_map::RawEntryBuilder<'a, &'static str, &'static str, ()>, 35 | ) -> linked_hash_map::RawEntryBuilder<'a, &'new str, &'new str, ()> { 36 | v 37 | } 38 | } 39 | 40 | #[test] 41 | fn test_index() { 42 | let mut map = LinkedHashMap::new(); 43 | map.insert(1, 10); 44 | map.insert(2, 20); 45 | assert_eq!(10, map[&1]); 46 | map[&2] = 22; 47 | assert_eq!(22, map[&2]); 48 | } 49 | 50 | #[test] 51 | fn test_insert_and_get() { 52 | let mut map = LinkedHashMap::new(); 53 | map.insert(1, 10); 54 | map.insert(2, 20); 55 | assert_eq!(map.get(&1), Some(&10)); 56 | assert_eq!(map.get(&2), Some(&20)); 57 | assert_eq!(map.len(), 2); 58 | } 59 | 60 | #[test] 61 | fn test_insert_update() { 62 | let mut map = LinkedHashMap::new(); 63 | map.insert("1".to_string(), vec![10, 10]); 64 | map.insert("1".to_string(), vec![10, 19]); 65 | assert_eq!(map.get(&"1".to_string()), Some(&vec![10, 19])); 66 | assert_eq!(map.len(), 1); 67 | } 68 | 69 | #[test] 70 | fn test_entry_insert_vacant() { 71 | let mut map = LinkedHashMap::new(); 72 | match map.entry("1".to_string()) { 73 | linked_hash_map::Entry::Vacant(e) => { 74 | assert_eq!(*e.insert(vec![10, 10]), vec![10, 10]); 75 | } 76 | _ => panic!("fail"), 77 | } 78 | assert!(map.contains_key("1")); 79 | assert_eq!(map["1"], vec![10, 10]); 80 | 81 | match map.entry("1".to_string()) { 82 | linked_hash_map::Entry::Occupied(mut e) => { 83 | assert_eq!(*e.get(), vec![10, 10]); 84 | assert_eq!(e.insert(vec![10, 16]), vec![10, 10]); 85 | } 86 | _ => panic!("fail"), 87 | } 88 | 89 | assert!(map.contains_key("1")); 90 | assert_eq!(map["1"], vec![10, 16]); 91 | 92 | match map.entry("1".to_string()) { 93 | linked_hash_map::Entry::Occupied(e) => { 94 | assert_eq!(e.remove(), vec![10, 16]); 95 | } 96 | _ => panic!("fail"), 97 | } 98 | } 99 | 100 | #[test] 101 | fn test_remove() { 102 | let mut map = LinkedHashMap::new(); 103 | map.insert(1, 10); 104 | map.insert(2, 20); 105 | map.insert(3, 30); 106 | map.insert(4, 40); 107 | map.insert(5, 50); 108 | map.remove(&3); 109 | map.remove(&4); 110 | assert!(map.get(&3).is_none()); 111 | assert!(map.get(&4).is_none()); 112 | map.insert(6, 60); 113 | map.insert(7, 70); 114 | map.insert(8, 80); 115 | assert_eq!(map.get(&6), Some(&60)); 116 | assert_eq!(map.get(&7), Some(&70)); 117 | assert_eq!(map.get(&8), Some(&80)); 118 | } 119 | 120 | #[test] 121 | fn test_pop() { 122 | let mut map = LinkedHashMap::new(); 123 | map.insert(1, 10); 124 | map.insert(2, 20); 125 | map.insert(3, 30); 126 | map.insert(4, 40); 127 | map.insert(5, 50); 128 | assert_eq!(map.pop_front(), Some((1, 10))); 129 | assert!(map.get(&1).is_none()); 130 | assert_eq!(map.pop_back(), Some((5, 50))); 131 | assert!(map.get(&5).is_none()); 132 | map.insert(6, 60); 133 | map.insert(7, 70); 134 | map.insert(8, 80); 135 | assert_eq!(map.pop_front(), Some((2, 20))); 136 | assert!(map.get(&2).is_none()); 137 | assert_eq!(map.pop_back(), Some((8, 80))); 138 | assert!(map.get(&8).is_none()); 139 | map.insert(3, 30); 140 | assert_eq!(map.pop_front(), Some((4, 40))); 141 | assert!(map.get(&4).is_none()); 142 | assert_eq!(map.pop_back(), Some((3, 30))); 143 | assert!(map.get(&3).is_none()); 144 | } 145 | 146 | #[test] 147 | fn test_move() { 148 | let to_back = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) { 149 | linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_back(), 150 | linked_hash_map::Entry::Vacant(_) => panic!(), 151 | }; 152 | 153 | let to_front = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) { 154 | linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_front(), 155 | linked_hash_map::Entry::Vacant(_) => panic!(), 156 | }; 157 | 158 | let mut map = LinkedHashMap::new(); 159 | map.insert(1, 10); 160 | map.insert(2, 20); 161 | map.insert(3, 30); 162 | map.insert(4, 40); 163 | map.insert(5, 50); 164 | 165 | to_back(&mut map, 1); 166 | assert_eq!(map.keys().copied().collect::>(), vec![2, 3, 4, 5, 1]); 167 | 168 | to_front(&mut map, 4); 169 | assert_eq!(map.keys().copied().collect::>(), vec![4, 2, 3, 5, 1]); 170 | 171 | to_back(&mut map, 3); 172 | assert_eq!(map.keys().copied().collect::>(), vec![4, 2, 5, 1, 3]); 173 | 174 | to_front(&mut map, 2); 175 | assert_eq!(map.keys().copied().collect::>(), vec![2, 4, 5, 1, 3]); 176 | 177 | to_back(&mut map, 3); 178 | assert_eq!(map.keys().copied().collect::>(), vec![2, 4, 5, 1, 3]); 179 | 180 | to_front(&mut map, 2); 181 | assert_eq!(map.keys().copied().collect::>(), vec![2, 4, 5, 1, 3]); 182 | } 183 | 184 | #[test] 185 | fn test_clear() { 186 | let mut map = LinkedHashMap::new(); 187 | map.insert(1, 10); 188 | map.insert(2, 20); 189 | map.clear(); 190 | assert!(map.get(&1).is_none()); 191 | assert!(map.get(&2).is_none()); 192 | assert!(map.is_empty()); 193 | } 194 | 195 | #[test] 196 | fn test_iter() { 197 | let mut map = LinkedHashMap::new(); 198 | 199 | // empty iter 200 | assert_eq!(None, map.iter().next()); 201 | 202 | map.insert("a", 10); 203 | map.insert("b", 20); 204 | map.insert("c", 30); 205 | 206 | // regular iter 207 | let mut iter = map.iter(); 208 | assert_eq!((&"a", &10), iter.next().unwrap()); 209 | assert_eq!((&"b", &20), iter.next().unwrap()); 210 | assert_eq!((&"c", &30), iter.next().unwrap()); 211 | assert_eq!(None, iter.next()); 212 | assert_eq!(None, iter.next()); 213 | 214 | let mut iter = map.iter(); 215 | assert_eq!((&"a", &10), iter.next().unwrap()); 216 | let mut iclone = iter.clone(); 217 | assert_eq!((&"b", &20), iter.next().unwrap()); 218 | assert_eq!((&"b", &20), iclone.next().unwrap()); 219 | assert_eq!((&"c", &30), iter.next().unwrap()); 220 | assert_eq!((&"c", &30), iclone.next().unwrap()); 221 | 222 | // reversed iter 223 | let mut rev_iter = map.iter().rev(); 224 | assert_eq!((&"c", &30), rev_iter.next().unwrap()); 225 | assert_eq!((&"b", &20), rev_iter.next().unwrap()); 226 | assert_eq!((&"a", &10), rev_iter.next().unwrap()); 227 | assert_eq!(None, rev_iter.next()); 228 | assert_eq!(None, rev_iter.next()); 229 | 230 | // mixed 231 | let mut mixed_iter = map.iter(); 232 | assert_eq!((&"a", &10), mixed_iter.next().unwrap()); 233 | assert_eq!((&"c", &30), mixed_iter.next_back().unwrap()); 234 | assert_eq!((&"b", &20), mixed_iter.next().unwrap()); 235 | assert_eq!(None, mixed_iter.next()); 236 | assert_eq!(None, mixed_iter.next_back()); 237 | } 238 | 239 | #[test] 240 | fn test_borrow() { 241 | #[derive(PartialEq, Eq, Hash)] 242 | struct Foo(Bar); 243 | #[derive(PartialEq, Eq, Hash)] 244 | struct Bar(i32); 245 | 246 | impl ::std::borrow::Borrow for Foo { 247 | fn borrow(&self) -> &Bar { 248 | &self.0 249 | } 250 | } 251 | 252 | let mut map = LinkedHashMap::new(); 253 | map.insert(Foo(Bar(1)), "a"); 254 | map.insert(Foo(Bar(2)), "b"); 255 | 256 | assert!(map.contains_key(&Bar(1))); 257 | assert!(map.contains_key(&Bar(2))); 258 | assert!(map.contains_key(&Foo(Bar(1)))); 259 | assert!(map.contains_key(&Foo(Bar(2)))); 260 | 261 | assert_eq!(map.get(&Bar(1)), Some(&"a")); 262 | assert_eq!(map.get(&Bar(2)), Some(&"b")); 263 | assert_eq!(map.get(&Foo(Bar(1))), Some(&"a")); 264 | assert_eq!(map.get(&Foo(Bar(2))), Some(&"b")); 265 | 266 | assert_eq!(map.get_mut(&Bar(1)), Some(&mut "a")); 267 | assert_eq!(map.get_mut(&Bar(2)), Some(&mut "b")); 268 | assert_eq!(map.get_mut(&Foo(Bar(1))), Some(&mut "a")); 269 | assert_eq!(map.get_mut(&Foo(Bar(2))), Some(&mut "b")); 270 | 271 | assert_eq!(map[&Bar(1)], "a"); 272 | assert_eq!(map[&Bar(2)], "b"); 273 | assert_eq!(map[&Foo(Bar(1))], "a"); 274 | assert_eq!(map[&Foo(Bar(2))], "b"); 275 | 276 | assert_eq!(map.remove(&Bar(1)), Some("a")); 277 | assert_eq!(map.remove(&Bar(2)), Some("b")); 278 | assert_eq!(map.remove(&Foo(Bar(1))), None); 279 | assert_eq!(map.remove(&Foo(Bar(2))), None); 280 | } 281 | 282 | #[test] 283 | fn test_iter_mut() { 284 | let mut map = LinkedHashMap::new(); 285 | map.insert("a", 10); 286 | map.insert("c", 30); 287 | map.insert("b", 20); 288 | 289 | { 290 | let mut iter = map.iter_mut(); 291 | let entry = iter.next().unwrap(); 292 | assert_eq!("a", *entry.0); 293 | *entry.1 = 17; 294 | 295 | assert_eq!(format!("{:?}", iter), "[(\"c\", 30), (\"b\", 20)]"); 296 | 297 | // reverse iterator 298 | let mut iter = iter.rev(); 299 | let entry = iter.next().unwrap(); 300 | assert_eq!("b", *entry.0); 301 | *entry.1 = 23; 302 | 303 | let entry = iter.next().unwrap(); 304 | assert_eq!("c", *entry.0); 305 | assert_eq!(None, iter.next()); 306 | assert_eq!(None, iter.next()); 307 | } 308 | 309 | assert_eq!(17, map[&"a"]); 310 | assert_eq!(23, map[&"b"]); 311 | } 312 | 313 | #[test] 314 | fn test_consuming_iter() { 315 | let map = { 316 | let mut map = LinkedHashMap::new(); 317 | map.insert("a", 10); 318 | map.insert("c", 30); 319 | map.insert("b", 20); 320 | map 321 | }; 322 | 323 | let mut iter = map.into_iter(); 324 | assert_eq!(Some(("a", 10)), iter.next()); 325 | assert_eq!(Some(("b", 20)), iter.next_back()); 326 | assert_eq!(iter.len(), 1); 327 | assert_eq!(format!("{:?}", iter), "[(\"c\", 30)]"); 328 | assert_eq!(Some(("c", 30)), iter.next()); 329 | assert_eq!(None, iter.next()); 330 | } 331 | 332 | #[test] 333 | fn test_consuming_iter_empty() { 334 | let map = LinkedHashMap::<&str, i32>::new(); 335 | let mut iter = map.into_iter(); 336 | assert_eq!(None, iter.next()); 337 | } 338 | 339 | #[test] 340 | fn test_consuming_iter_with_free_list() { 341 | let mut map = LinkedHashMap::new(); 342 | map.insert("a", 10); 343 | map.insert("c", 30); 344 | map.insert("b", 20); 345 | map.remove("a"); 346 | map.remove("b"); 347 | 348 | let mut iter = map.into_iter(); 349 | assert_eq!(Some(("c", 30)), iter.next()); 350 | assert_eq!(None, iter.next()); 351 | } 352 | 353 | #[test] 354 | fn test_into_iter_drop() { 355 | struct Counter<'a>(&'a mut usize); 356 | 357 | impl Drop for Counter<'_> { 358 | fn drop(&mut self) { 359 | *self.0 += 1; 360 | } 361 | } 362 | 363 | let mut a = 0; 364 | let mut b = 0; 365 | let mut c = 0; 366 | 367 | { 368 | let mut map = LinkedHashMap::new(); 369 | map.insert("a", Counter(&mut a)); 370 | map.insert("b", Counter(&mut b)); 371 | map.insert("c", Counter(&mut c)); 372 | 373 | let mut iter = map.into_iter(); 374 | assert_eq!(iter.next().map(|p| p.0), Some("a")); 375 | assert_eq!(iter.next_back().map(|p| p.0), Some("c")); 376 | } 377 | 378 | assert_eq!(a, 1); 379 | assert_eq!(b, 1); 380 | assert_eq!(c, 1); 381 | } 382 | 383 | #[test] 384 | fn test_drain() { 385 | use std::{cell::Cell, rc::Rc}; 386 | 387 | struct Counter(Rc>); 388 | 389 | impl Drop for Counter { 390 | fn drop(&mut self) { 391 | self.0.set(self.0.get() + 1); 392 | } 393 | } 394 | 395 | let mut map = LinkedHashMap::new(); 396 | 397 | let a = Rc::new(Cell::new(0)); 398 | let b = Rc::new(Cell::new(0)); 399 | let c = Rc::new(Cell::new(0)); 400 | 401 | map.insert("a", Counter(a.clone())); 402 | map.insert("b", Counter(b.clone())); 403 | map.insert("c", Counter(c.clone())); 404 | 405 | let mut iter = map.drain(); 406 | assert_eq!(iter.next().map(|p| p.0), Some("a")); 407 | assert_eq!(iter.next_back().map(|p| p.0), Some("c")); 408 | assert_eq!(iter.next_back().map(|p| p.0), Some("b")); 409 | assert!(iter.next().is_none()); 410 | assert!(iter.next_back().is_none()); 411 | 412 | drop(iter); 413 | assert_eq!(map.len(), 0); 414 | 415 | assert_eq!(a.get(), 1); 416 | assert_eq!(b.get(), 1); 417 | assert_eq!(c.get(), 1); 418 | 419 | map.insert("a", Counter(a.clone())); 420 | map.insert("b", Counter(b.clone())); 421 | map.insert("c", Counter(c.clone())); 422 | 423 | let mut iter = map.drain(); 424 | assert_eq!(iter.next().map(|p| p.0), Some("a")); 425 | assert_eq!(iter.next().map(|p| p.0), Some("b")); 426 | assert_eq!(iter.next_back().map(|p| p.0), Some("c")); 427 | assert!(iter.next().is_none()); 428 | assert!(iter.next_back().is_none()); 429 | 430 | drop(iter); 431 | assert_eq!(map.len(), 0); 432 | 433 | assert_eq!(a.get(), 2); 434 | assert_eq!(b.get(), 2); 435 | assert_eq!(c.get(), 2); 436 | 437 | map.insert("a", Counter(a.clone())); 438 | map.insert("b", Counter(b.clone())); 439 | map.insert("c", Counter(c.clone())); 440 | 441 | map.drain(); 442 | assert_eq!(map.len(), 0); 443 | 444 | assert_eq!(a.get(), 3); 445 | assert_eq!(b.get(), 3); 446 | assert_eq!(c.get(), 3); 447 | } 448 | 449 | #[test] 450 | fn test_send_sync() { 451 | fn is_send_sync() {} 452 | 453 | is_send_sync::>(); 454 | is_send_sync::>(); 455 | is_send_sync::>(); 456 | is_send_sync::>(); 457 | is_send_sync::>(); 458 | is_send_sync::>(); 459 | is_send_sync::>(); 460 | is_send_sync::>(); 461 | is_send_sync::>(); 462 | is_send_sync::>(); 463 | } 464 | 465 | #[test] 466 | fn test_retain() { 467 | use std::{cell::Cell, rc::Rc}; 468 | 469 | let xs = [1, 2, 3, 4, 5, 6]; 470 | let mut map: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); 471 | map.retain(|_, v| *v % 2 == 0); 472 | assert_eq!(map.len(), 3); 473 | assert!(map.contains_key("2")); 474 | assert!(map.contains_key("4")); 475 | assert!(map.contains_key("6")); 476 | 477 | struct Counter(Rc>); 478 | 479 | impl Drop for Counter { 480 | fn drop(&mut self) { 481 | self.0.set(self.0.get() + 1); 482 | } 483 | } 484 | 485 | let c = Rc::new(Cell::new(0)); 486 | 487 | let mut map = LinkedHashMap::new(); 488 | map.insert(1, Counter(Rc::clone(&c))); 489 | map.insert(2, Counter(Rc::clone(&c))); 490 | map.insert(3, Counter(Rc::clone(&c))); 491 | map.insert(4, Counter(Rc::clone(&c))); 492 | 493 | map.retain(|k, _| *k % 2 == 0); 494 | 495 | assert!(c.get() == 2); 496 | drop(map); 497 | assert!(c.get() == 4); 498 | } 499 | 500 | #[test] 501 | fn test_order_equality() { 502 | let xs = [1, 2, 3, 4, 5, 6]; 503 | let mut map1: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); 504 | let mut map2: LinkedHashMap = xs.iter().map(|i| (i.to_string(), *i)).collect(); 505 | 506 | assert_eq!(map1, map2); 507 | 508 | map1.to_front("4"); 509 | assert_ne!(map1, map2); 510 | 511 | map2.to_front("4"); 512 | assert_eq!(map1, map2); 513 | } 514 | 515 | #[test] 516 | fn test_replace() { 517 | let mut map = LinkedHashMap::new(); 518 | 519 | map.insert(1, 1); 520 | map.insert(2, 2); 521 | map.insert(3, 3); 522 | map.insert(4, 4); 523 | 524 | assert!(map 525 | .iter() 526 | .map(|(k, v)| (*k, *v)) 527 | .eq([(1, 1), (2, 2), (3, 3), (4, 4)].iter().copied())); 528 | 529 | map.insert(3, 5); 530 | 531 | assert!(map 532 | .iter() 533 | .map(|(k, v)| (*k, *v)) 534 | .eq([(1, 1), (2, 2), (4, 4), (3, 5)].iter().copied())); 535 | 536 | map.replace(2, 6); 537 | 538 | assert!(map 539 | .iter() 540 | .map(|(k, v)| (*k, *v)) 541 | .eq([(1, 1), (2, 6), (4, 4), (3, 5)].iter().copied())); 542 | } 543 | 544 | #[test] 545 | fn test_reserve() { 546 | let mut map = LinkedHashMap::new(); 547 | 548 | map.insert(1, 1); 549 | map.insert(2, 2); 550 | map.insert(3, 3); 551 | map.insert(4, 4); 552 | 553 | assert!(map.capacity() - map.len() < 100); 554 | map.reserve(100); 555 | assert!(map.capacity() - map.len() >= 100); 556 | } 557 | 558 | #[test] 559 | fn test_shrink_to_fit_resize() { 560 | let mut map = LinkedHashMap::new(); 561 | map.shrink_to_fit(); 562 | 563 | for i in 0..100 { 564 | map.insert(i, i); 565 | } 566 | map.shrink_to_fit(); 567 | 568 | for _ in 0..50 { 569 | map.pop_front(); 570 | map.shrink_to_fit(); 571 | } 572 | 573 | assert_eq!(map.len(), 50); 574 | for i in 50..100 { 575 | assert_eq!(map.get(&i).unwrap(), &i); 576 | } 577 | } 578 | 579 | #[test] 580 | fn test_cursor_mut_current() { 581 | let mut map = LinkedHashMap::new(); 582 | 583 | map.insert(3, 3); 584 | 585 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 586 | let mut cursor = entry.cursor_mut(); 587 | let value = cursor.current().unwrap(); 588 | assert_eq!(value, (&3, &mut 3)); 589 | *value.1 = 5; 590 | let value = cursor.current().unwrap(); 591 | assert_eq!(value, (&3, &mut 5)); 592 | } 593 | } 594 | 595 | #[test] 596 | fn test_cursor_mut_move_next() { 597 | let mut map = LinkedHashMap::new(); 598 | 599 | map.insert(3, 3); 600 | map.insert(4, 4); 601 | map.insert(5, 5); 602 | map.insert(6, 6); 603 | 604 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 605 | let mut cursor = entry.cursor_mut(); 606 | let value = cursor.current(); 607 | assert!(&value.is_some()); 608 | assert_eq!(value.unwrap().1, &mut 3); 609 | cursor.move_next(); 610 | let value = cursor.current(); 611 | assert!(&value.is_some()); 612 | assert_eq!(value.unwrap().1, &mut 4); 613 | cursor.move_next(); 614 | let value = cursor.current(); 615 | assert!(&value.is_some()); 616 | assert_eq!(value.unwrap().1, &mut 5); 617 | cursor.move_next(); 618 | let value = cursor.current(); 619 | assert!(&value.is_some()); 620 | assert_eq!(value.unwrap().1, &mut 6); 621 | cursor.move_next(); 622 | let value = cursor.current(); 623 | assert!(value.is_none()); 624 | cursor.move_next(); 625 | let value = cursor.current(); 626 | assert!(value.is_some()); 627 | assert_eq!(value.unwrap().1, &mut 3); 628 | cursor.move_next(); 629 | let value = cursor.current(); 630 | assert!(&value.is_some()); 631 | assert_eq!(value.unwrap().1, &mut 4); 632 | } 633 | } 634 | 635 | #[test] 636 | fn test_cursor_mut_move_prev() { 637 | let mut map = LinkedHashMap::new(); 638 | 639 | map.insert(3, 3); 640 | 641 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 642 | let mut cursor = entry.cursor_mut(); 643 | cursor.move_prev(); 644 | let value = cursor.current(); 645 | assert!(value.is_none()); 646 | cursor.move_prev(); 647 | let value = cursor.current(); 648 | assert!(&value.is_some()); 649 | assert_eq!(value.unwrap().1, &mut 3); 650 | } 651 | } 652 | 653 | #[test] 654 | fn test_cursor_mut_pick_next() { 655 | let mut map = LinkedHashMap::new(); 656 | 657 | map.insert(3, 3); 658 | map.insert(4, 4); 659 | 660 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 661 | let mut cursor = entry.cursor_mut(); 662 | let next = cursor.peek_next(); 663 | assert!(&next.is_some()); 664 | assert_eq!(next.unwrap().1, &mut 4); 665 | cursor.move_next(); 666 | let next = cursor.peek_next(); 667 | assert!(&next.is_none()); 668 | cursor.move_next(); 669 | let next = cursor.peek_next(); 670 | assert!(&next.is_some()); 671 | let value = next.as_ref().unwrap().to_owned(); 672 | assert_eq!(*value.1, 3); 673 | *next.unwrap().1 = 5; 674 | let next = cursor.peek_next(); 675 | assert!(&next.is_some()); 676 | assert_eq!(next.unwrap().1, &mut 5); 677 | } 678 | } 679 | 680 | #[test] 681 | fn test_cursor_mut_pick_prev() { 682 | let mut map = LinkedHashMap::new(); 683 | 684 | map.insert(3, 3); 685 | map.insert(4, 4); 686 | 687 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 688 | let mut cursor = entry.cursor_mut(); 689 | let next = cursor.peek_prev(); 690 | assert!(&next.is_none()); 691 | cursor.move_prev(); 692 | let next = cursor.peek_prev(); 693 | assert!(&next.is_some()); 694 | assert_eq!(next.unwrap(), (&4, &mut 4)); 695 | } 696 | } 697 | 698 | #[test] 699 | fn test_cursor_mut_insert_before() { 700 | let mut map = LinkedHashMap::new(); 701 | 702 | map.insert(3, 3); 703 | map.insert(4, 4); 704 | 705 | // Insert new element in the middle 706 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(4) { 707 | entry.cursor_mut().insert_before(5, 5); 708 | assert!(map 709 | .iter() 710 | .map(|(k, v)| (*k, *v)) 711 | .eq([(3, 3), (5, 5), (4, 4)].iter().copied())); 712 | } 713 | 714 | // Insert new element at the very end of the list 715 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 716 | let mut cursor = entry.cursor_mut(); 717 | cursor.move_prev(); 718 | cursor.insert_before(6, 6); 719 | assert!(map 720 | .iter() 721 | .map(|(k, v)| (*k, *v)) 722 | .eq([(3, 3), (5, 5), (4, 4), (6, 6)].iter().copied())); 723 | } 724 | 725 | // Relocate element and override value 726 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(5) { 727 | entry.cursor_mut().insert_before(4, 42); 728 | assert!(map 729 | .iter() 730 | .map(|(k, v)| (*k, *v)) 731 | .eq([(3, 3), (4, 42), (5, 5), (6, 6)].iter().copied())); 732 | } 733 | } 734 | 735 | #[test] 736 | fn test_cursor_mut_insert_after() { 737 | let mut map = LinkedHashMap::new(); 738 | 739 | map.insert(3, 3); 740 | map.insert(4, 4); 741 | 742 | // Insert new element in the middle. 743 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 744 | entry.cursor_mut().insert_after(5, 5); 745 | assert!(map 746 | .iter() 747 | .map(|(k, v)| (*k, *v)) 748 | .eq([(3, 3), (5, 5), (4, 4)].iter().copied())); 749 | } 750 | 751 | // Insert new element as the first one. 752 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(4) { 753 | let mut cursor = entry.cursor_mut(); 754 | cursor.move_next(); 755 | cursor.insert_after(6, 6); 756 | assert!(map 757 | .iter() 758 | .map(|(k, v)| (*k, *v)) 759 | .eq([(6, 6), (3, 3), (5, 5), (4, 4)].iter().copied())); 760 | } 761 | } 762 | 763 | #[test] 764 | fn test_cursor_mut_insert_before_itself() { 765 | let mut map = LinkedHashMap::new(); 766 | 767 | map.insert(2, 2); 768 | map.insert(3, 3); 769 | map.insert(4, 4); 770 | 771 | // Insert a new value before its key. This is a corner case that needs to be 772 | // handled explicitly. 773 | if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) { 774 | entry.cursor_mut().insert_before(3, 5); 775 | assert!(map 776 | .iter() 777 | .map(|(k, v)| (*k, *v)) 778 | .eq([(2, 2), (3, 5), (4, 4)].iter().copied())); 779 | } 780 | } 781 | 782 | #[test] 783 | fn test_cursor_front_mut() { 784 | let mut map: LinkedHashMap = LinkedHashMap::new(); 785 | // The `CursorMut`` in an empty LinkedHashMap will always return `None` as its 786 | // current element, regardless of any move in any direction. 787 | let mut cursor = map.cursor_front_mut(); 788 | assert!(cursor.current().is_none()); 789 | cursor.move_next(); 790 | assert!(cursor.current().is_none()); 791 | cursor.insert_after(1, 1); 792 | cursor.move_next(); 793 | assert!(cursor.current().is_some()); 794 | assert_eq!(cursor.current().unwrap().1, &mut 1); 795 | cursor.move_next(); 796 | assert!(cursor.current().is_none()); 797 | 798 | assert!(map 799 | .iter() 800 | .map(|(k, v)| (*k, *v)) 801 | .eq([(1, 1)].iter().copied())); 802 | 803 | map.insert(2, 2); 804 | map.insert(3, 3); 805 | 806 | let mut cursor = map.cursor_front_mut(); 807 | assert!(cursor.current().is_some()); 808 | assert_eq!(cursor.current().unwrap().1, &mut 1); 809 | } 810 | 811 | #[test] 812 | fn test_cursor_back_mut() { 813 | let mut map: LinkedHashMap = LinkedHashMap::new(); 814 | 815 | map.insert(1, 1); 816 | map.insert(2, 2); 817 | map.insert(3, 3); 818 | 819 | let mut cursor = map.cursor_back_mut(); 820 | assert!(cursor.current().is_some()); 821 | assert_eq!(cursor.current().unwrap().1, &mut 3); 822 | } 823 | -------------------------------------------------------------------------------- /tests/linked_hash_set.rs: -------------------------------------------------------------------------------- 1 | use hashlink::linked_hash_set::{self, LinkedHashSet}; 2 | use hashlink::DefaultHashBuilder; 3 | 4 | #[allow(dead_code)] 5 | fn assert_covariance() { 6 | fn set<'new>(v: LinkedHashSet<&'static str>) -> LinkedHashSet<&'new str> { 7 | v 8 | } 9 | 10 | fn iter<'a, 'new>( 11 | v: linked_hash_set::Iter<'a, &'static str>, 12 | ) -> linked_hash_set::Iter<'a, &'new str> { 13 | v 14 | } 15 | 16 | fn into_iter<'new>( 17 | v: linked_hash_set::IntoIter<&'static str>, 18 | ) -> linked_hash_set::IntoIter<&'new str> { 19 | v 20 | } 21 | 22 | fn difference<'a, 'new>( 23 | v: linked_hash_set::Difference<'a, &'static str, DefaultHashBuilder>, 24 | ) -> linked_hash_set::Difference<'a, &'new str, DefaultHashBuilder> { 25 | v 26 | } 27 | 28 | fn symmetric_difference<'a, 'new>( 29 | v: linked_hash_set::SymmetricDifference<'a, &'static str, DefaultHashBuilder>, 30 | ) -> linked_hash_set::SymmetricDifference<'a, &'new str, DefaultHashBuilder> { 31 | v 32 | } 33 | 34 | fn intersection<'a, 'new>( 35 | v: linked_hash_set::Intersection<'a, &'static str, DefaultHashBuilder>, 36 | ) -> linked_hash_set::Intersection<'a, &'new str, DefaultHashBuilder> { 37 | v 38 | } 39 | 40 | fn union<'a, 'new>( 41 | v: linked_hash_set::Union<'a, &'static str, DefaultHashBuilder>, 42 | ) -> linked_hash_set::Union<'a, &'new str, DefaultHashBuilder> { 43 | v 44 | } 45 | 46 | fn drain<'new>( 47 | d: linked_hash_set::Drain<'static, &'static str>, 48 | ) -> linked_hash_set::Drain<'new, &'new str> { 49 | d 50 | } 51 | } 52 | 53 | #[test] 54 | fn test_zero_capacities() { 55 | type HS = LinkedHashSet; 56 | 57 | let s = HS::new(); 58 | assert_eq!(s.capacity(), 0); 59 | 60 | let s = HS::default(); 61 | assert_eq!(s.capacity(), 0); 62 | 63 | let s = HS::with_hasher(DefaultHashBuilder::default()); 64 | assert_eq!(s.capacity(), 0); 65 | 66 | let s = HS::with_capacity(0); 67 | assert_eq!(s.capacity(), 0); 68 | 69 | let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default()); 70 | assert_eq!(s.capacity(), 0); 71 | 72 | let mut s = HS::new(); 73 | s.insert(1); 74 | s.insert(2); 75 | s.remove(&1); 76 | s.remove(&2); 77 | s.shrink_to_fit(); 78 | assert_eq!(s.capacity(), 0); 79 | 80 | let mut s = HS::new(); 81 | s.reserve(0); 82 | assert_eq!(s.capacity(), 0); 83 | } 84 | 85 | #[test] 86 | fn test_disjoint() { 87 | let mut xs = LinkedHashSet::new(); 88 | let mut ys = LinkedHashSet::new(); 89 | assert!(xs.is_disjoint(&ys)); 90 | assert!(ys.is_disjoint(&xs)); 91 | assert!(xs.insert(5)); 92 | assert!(ys.insert(11)); 93 | assert!(xs.is_disjoint(&ys)); 94 | assert!(ys.is_disjoint(&xs)); 95 | assert!(xs.insert(7)); 96 | assert!(xs.insert(19)); 97 | assert!(xs.insert(4)); 98 | assert!(ys.insert(2)); 99 | assert!(ys.insert(-11)); 100 | assert!(xs.is_disjoint(&ys)); 101 | assert!(ys.is_disjoint(&xs)); 102 | assert!(ys.insert(7)); 103 | assert!(!xs.is_disjoint(&ys)); 104 | assert!(!ys.is_disjoint(&xs)); 105 | } 106 | 107 | #[test] 108 | fn test_subset_and_superset() { 109 | let mut a = LinkedHashSet::new(); 110 | assert!(a.insert(0)); 111 | assert!(a.insert(5)); 112 | assert!(a.insert(11)); 113 | assert!(a.insert(7)); 114 | 115 | let mut b = LinkedHashSet::new(); 116 | assert!(b.insert(0)); 117 | assert!(b.insert(7)); 118 | assert!(b.insert(19)); 119 | assert!(b.insert(250)); 120 | assert!(b.insert(11)); 121 | assert!(b.insert(200)); 122 | 123 | assert!(!a.is_subset(&b)); 124 | assert!(!a.is_superset(&b)); 125 | assert!(!b.is_subset(&a)); 126 | assert!(!b.is_superset(&a)); 127 | 128 | assert!(b.insert(5)); 129 | 130 | assert!(a.is_subset(&b)); 131 | assert!(!a.is_superset(&b)); 132 | assert!(!b.is_subset(&a)); 133 | assert!(b.is_superset(&a)); 134 | } 135 | 136 | #[test] 137 | fn test_iterate() { 138 | let mut a = LinkedHashSet::new(); 139 | for i in 0..32 { 140 | assert!(a.insert(i)); 141 | } 142 | let mut observed: u32 = 0; 143 | for k in &a { 144 | observed |= 1 << *k; 145 | } 146 | assert_eq!(observed, 0xFFFF_FFFF); 147 | } 148 | 149 | #[test] 150 | fn test_intersection() { 151 | let mut a = LinkedHashSet::new(); 152 | let mut b = LinkedHashSet::new(); 153 | 154 | assert!(a.insert(11)); 155 | assert!(a.insert(1)); 156 | assert!(a.insert(3)); 157 | assert!(a.insert(77)); 158 | assert!(a.insert(103)); 159 | assert!(a.insert(5)); 160 | assert!(a.insert(-5)); 161 | 162 | assert!(b.insert(2)); 163 | assert!(b.insert(11)); 164 | assert!(b.insert(77)); 165 | assert!(b.insert(-9)); 166 | assert!(b.insert(-42)); 167 | assert!(b.insert(5)); 168 | assert!(b.insert(3)); 169 | 170 | let mut i = 0; 171 | let expected = [3, 5, 11, 77]; 172 | for x in a.intersection(&b) { 173 | assert!(expected.contains(x)); 174 | i += 1 175 | } 176 | assert_eq!(i, expected.len()); 177 | } 178 | 179 | #[test] 180 | fn test_difference() { 181 | let mut a = LinkedHashSet::new(); 182 | let mut b = LinkedHashSet::new(); 183 | 184 | assert!(a.insert(1)); 185 | assert!(a.insert(3)); 186 | assert!(a.insert(5)); 187 | assert!(a.insert(9)); 188 | assert!(a.insert(11)); 189 | 190 | assert!(b.insert(3)); 191 | assert!(b.insert(9)); 192 | 193 | let mut i = 0; 194 | let expected = [1, 5, 11]; 195 | for x in a.difference(&b) { 196 | assert!(expected.contains(x)); 197 | i += 1 198 | } 199 | assert_eq!(i, expected.len()); 200 | } 201 | 202 | #[test] 203 | fn test_symmetric_difference() { 204 | let mut a = LinkedHashSet::new(); 205 | let mut b = LinkedHashSet::new(); 206 | 207 | assert!(a.insert(1)); 208 | assert!(a.insert(3)); 209 | assert!(a.insert(5)); 210 | assert!(a.insert(9)); 211 | assert!(a.insert(11)); 212 | 213 | assert!(b.insert(-2)); 214 | assert!(b.insert(3)); 215 | assert!(b.insert(9)); 216 | assert!(b.insert(14)); 217 | assert!(b.insert(22)); 218 | 219 | let mut i = 0; 220 | let expected = [-2, 1, 5, 11, 14, 22]; 221 | for x in a.symmetric_difference(&b) { 222 | assert!(expected.contains(x)); 223 | i += 1 224 | } 225 | assert_eq!(i, expected.len()); 226 | } 227 | 228 | #[test] 229 | fn test_union() { 230 | let mut a = LinkedHashSet::new(); 231 | let mut b = LinkedHashSet::new(); 232 | 233 | assert!(a.insert(1)); 234 | assert!(a.insert(3)); 235 | assert!(a.insert(5)); 236 | assert!(a.insert(9)); 237 | assert!(a.insert(11)); 238 | assert!(a.insert(16)); 239 | assert!(a.insert(19)); 240 | assert!(a.insert(24)); 241 | 242 | assert!(b.insert(-2)); 243 | assert!(b.insert(1)); 244 | assert!(b.insert(5)); 245 | assert!(b.insert(9)); 246 | assert!(b.insert(13)); 247 | assert!(b.insert(19)); 248 | 249 | let mut i = 0; 250 | let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]; 251 | for x in a.union(&b) { 252 | assert!(expected.contains(x)); 253 | i += 1 254 | } 255 | assert_eq!(i, expected.len()); 256 | } 257 | 258 | #[test] 259 | fn test_from_iter() { 260 | let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 261 | 262 | let set: LinkedHashSet<_> = xs.iter().cloned().collect(); 263 | 264 | for x in &xs { 265 | assert!(set.contains(x)); 266 | } 267 | } 268 | 269 | #[test] 270 | fn test_move_iter() { 271 | let hs = { 272 | let mut hs = LinkedHashSet::new(); 273 | 274 | hs.insert('a'); 275 | hs.insert('b'); 276 | 277 | hs 278 | }; 279 | 280 | let v = hs.into_iter().collect::>(); 281 | assert!(v == ['a', 'b'] || v == ['b', 'a']); 282 | } 283 | 284 | #[test] 285 | fn test_eq() { 286 | let mut s1 = LinkedHashSet::new(); 287 | 288 | s1.insert(1); 289 | s1.insert(2); 290 | s1.insert(3); 291 | 292 | let mut s2 = LinkedHashSet::new(); 293 | 294 | s2.insert(1); 295 | s2.insert(2); 296 | 297 | assert!(s1 != s2); 298 | 299 | s2.insert(3); 300 | 301 | assert_eq!(s1, s2); 302 | } 303 | 304 | #[test] 305 | fn test_show() { 306 | let mut set = LinkedHashSet::new(); 307 | let empty = LinkedHashSet::::new(); 308 | 309 | set.insert(1); 310 | set.insert(2); 311 | 312 | let set_str = format!("{:?}", set); 313 | 314 | assert!(set_str == "{1, 2}" || set_str == "{2, 1}"); 315 | assert_eq!(format!("{:?}", empty), "{}"); 316 | } 317 | 318 | #[test] 319 | fn test_trivial_drain() { 320 | let mut s = LinkedHashSet::::new(); 321 | for _ in s.drain() {} 322 | assert!(s.is_empty()); 323 | drop(s); 324 | 325 | let mut s = LinkedHashSet::::new(); 326 | drop(s.drain()); 327 | assert!(s.is_empty()); 328 | } 329 | 330 | #[test] 331 | fn test_drain() { 332 | let mut s: LinkedHashSet<_> = (1..100).collect(); 333 | 334 | for _ in 0..20 { 335 | assert_eq!(s.len(), 99); 336 | 337 | { 338 | let mut last_i = 0; 339 | let mut d = s.drain(); 340 | for (i, x) in d.by_ref().take(50).enumerate() { 341 | last_i = i; 342 | assert!(x != 0); 343 | } 344 | assert_eq!(last_i, 49); 345 | } 346 | 347 | assert_eq!((&s).into_iter().count(), 0); 348 | 349 | s.extend(1..100); 350 | } 351 | } 352 | 353 | #[test] 354 | fn test_replace() { 355 | use core::hash; 356 | 357 | #[derive(Debug)] 358 | struct Foo(&'static str, i32); 359 | 360 | impl PartialEq for Foo { 361 | fn eq(&self, other: &Self) -> bool { 362 | self.0 == other.0 363 | } 364 | } 365 | 366 | impl Eq for Foo {} 367 | 368 | impl hash::Hash for Foo { 369 | fn hash(&self, h: &mut H) { 370 | self.0.hash(h); 371 | } 372 | } 373 | 374 | impl Foo { 375 | fn really_eq(&self, other: &Self) -> bool { 376 | self.0 == other.0 && self.1 == other.1 377 | } 378 | } 379 | 380 | let mut s = LinkedHashSet::new(); 381 | assert_eq!(s.replace(Foo("a", 1)), None); 382 | assert_eq!(s.len(), 1); 383 | assert_eq!( 384 | s.replace(Foo("a", 2)).map(|f| f.really_eq(&Foo("a", 1))), 385 | Some(true) 386 | ); 387 | assert_eq!(s.len(), 1); 388 | 389 | let mut it = s.iter(); 390 | assert_eq!(it.next().map(|f| f.really_eq(&Foo("a", 2))), Some(true)); 391 | assert_eq!(it.next(), None); 392 | } 393 | 394 | #[test] 395 | fn test_extend_ref() { 396 | let mut a = LinkedHashSet::new(); 397 | a.insert(1); 398 | 399 | a.extend(&[2, 3, 4]); 400 | 401 | assert_eq!(a.len(), 4); 402 | assert!(a.contains(&1)); 403 | assert!(a.contains(&2)); 404 | assert!(a.contains(&3)); 405 | assert!(a.contains(&4)); 406 | 407 | let mut b = LinkedHashSet::new(); 408 | b.insert(5); 409 | b.insert(6); 410 | 411 | a.extend(&b); 412 | 413 | assert_eq!(a.len(), 6); 414 | assert!(a.contains(&1)); 415 | assert!(a.contains(&2)); 416 | assert!(a.contains(&3)); 417 | assert!(a.contains(&4)); 418 | assert!(a.contains(&5)); 419 | assert!(a.contains(&6)); 420 | } 421 | 422 | #[test] 423 | fn test_retain() { 424 | let xs = [1, 2, 3, 4, 5, 6]; 425 | let mut set: LinkedHashSet = xs.iter().cloned().collect(); 426 | set.retain(|&k| k % 2 == 0); 427 | assert_eq!(set.len(), 3); 428 | assert!(set.contains(&2)); 429 | assert!(set.contains(&4)); 430 | assert!(set.contains(&6)); 431 | } 432 | 433 | #[test] 434 | fn test_retain_with_order() { 435 | let xs = [1, 2, 3, 4, 5, 6]; 436 | let mut set: LinkedHashSet = xs.iter().cloned().collect(); 437 | let mut vec = Vec::new(); 438 | set.retain_with_order(|&k| { 439 | if k % 2 == 0 { 440 | true 441 | } else { 442 | vec.push(k); 443 | false 444 | } 445 | }); 446 | assert_eq!(vec![1, 3, 5], vec); 447 | } 448 | 449 | #[test] 450 | fn insert_order() { 451 | let mut set = LinkedHashSet::new(); 452 | set.insert(1); 453 | set.insert(2); 454 | set.insert(3); 455 | set.insert(4); 456 | assert_eq!( 457 | set.clone().into_iter().collect::>(), 458 | vec![1, 2, 3, 4] 459 | ); 460 | assert_eq!(set.into_iter().collect::>(), vec![1, 2, 3, 4]); 461 | } 462 | 463 | #[test] 464 | fn front_back() { 465 | let mut set = LinkedHashSet::new(); 466 | set.insert(1); 467 | set.insert(2); 468 | set.insert(3); 469 | set.insert(4); 470 | assert_eq!(set.front(), Some(&1)); 471 | assert_eq!(set.back(), Some(&4)); 472 | assert_eq!(set.pop_back(), Some(4)); 473 | assert_eq!(set.back(), Some(&3)); 474 | assert_eq!(set.pop_front(), Some(1)); 475 | assert_eq!(set.front(), Some(&2)); 476 | } 477 | 478 | #[test] 479 | fn double_ended_iter() { 480 | let mut set = LinkedHashSet::new(); 481 | set.insert(1); 482 | set.insert(2); 483 | set.insert(3); 484 | set.insert(4); 485 | 486 | let mut iter = set.iter(); 487 | assert_eq!(iter.next(), Some(&1)); 488 | assert_eq!(iter.next(), Some(&2)); 489 | assert_eq!(iter.next_back(), Some(&4)); 490 | assert_eq!(iter.next_back(), Some(&3)); 491 | assert_eq!(iter.next_back(), None); 492 | assert_eq!(iter.next(), None); 493 | assert_eq!(iter.next_back(), None); 494 | 495 | let mut iter = set.drain(); 496 | assert_eq!(iter.next(), Some(1)); 497 | assert_eq!(iter.next(), Some(2)); 498 | assert_eq!(iter.next_back(), Some(4)); 499 | assert_eq!(iter.next_back(), Some(3)); 500 | assert_eq!(iter.next_back(), None); 501 | assert_eq!(iter.next(), None); 502 | assert_eq!(iter.next_back(), None); 503 | drop(iter); 504 | 505 | set.insert(1); 506 | set.insert(2); 507 | set.insert(3); 508 | set.insert(4); 509 | 510 | let mut iter = set.into_iter(); 511 | assert_eq!(iter.next(), Some(1)); 512 | assert_eq!(iter.next(), Some(2)); 513 | assert_eq!(iter.next_back(), Some(4)); 514 | assert_eq!(iter.next_back(), Some(3)); 515 | assert_eq!(iter.next_back(), None); 516 | assert_eq!(iter.next(), None); 517 | assert_eq!(iter.next_back(), None); 518 | } 519 | 520 | #[test] 521 | fn to_back_front_order() { 522 | let mut set = LinkedHashSet::new(); 523 | set.insert(1); 524 | set.insert(2); 525 | set.insert(3); 526 | set.insert(4); 527 | 528 | assert_eq!(set.back().copied(), Some(4)); 529 | assert_eq!(set.front().copied(), Some(1)); 530 | set.to_back(&2); 531 | assert_eq!(set.back().copied(), Some(2)); 532 | set.to_front(&3); 533 | assert_eq!(set.front().copied(), Some(3)); 534 | } 535 | 536 | #[test] 537 | fn test_order_equality() { 538 | let xs = [1, 2, 3, 4, 5, 6]; 539 | let mut set1: LinkedHashSet = xs.iter().copied().collect(); 540 | let mut set2: LinkedHashSet = xs.iter().copied().collect(); 541 | 542 | assert_eq!(set1, set2); 543 | 544 | set1.to_front(&4); 545 | assert_ne!(set1, set2); 546 | 547 | set2.to_front(&4); 548 | assert_eq!(set1, set2); 549 | } 550 | -------------------------------------------------------------------------------- /tests/lru_cache.rs: -------------------------------------------------------------------------------- 1 | use hashlink::LruCache; 2 | 3 | #[test] 4 | fn test_put_and_get() { 5 | let mut cache = LruCache::new(2); 6 | cache.insert(1, 10); 7 | cache.insert(2, 20); 8 | assert_eq!(cache.get_mut(&1), Some(&mut 10)); 9 | assert_eq!(cache.get_mut(&2), Some(&mut 20)); 10 | assert_eq!(cache.len(), 2); 11 | } 12 | 13 | #[test] 14 | fn test_put_update() { 15 | let mut cache = LruCache::new(1); 16 | cache.insert("1", 10); 17 | cache.insert("1", 19); 18 | assert_eq!(cache.get_mut("1"), Some(&mut 19)); 19 | assert_eq!(cache.len(), 1); 20 | } 21 | 22 | #[test] 23 | fn test_contains_key() { 24 | let mut cache = LruCache::new(1); 25 | cache.insert("1", 10); 26 | assert!(cache.contains_key("1")); 27 | } 28 | 29 | #[test] 30 | fn test_expire_lru() { 31 | let mut cache = LruCache::new(2); 32 | cache.insert("foo1", "bar1"); 33 | cache.insert("foo2", "bar2"); 34 | cache.insert("foo3", "bar3"); 35 | assert!(cache.get_mut("foo1").is_none()); 36 | cache.insert("foo2", "bar2update"); 37 | cache.insert("foo4", "bar4"); 38 | assert!(cache.get_mut("foo3").is_none()); 39 | } 40 | 41 | #[test] 42 | fn test_pop() { 43 | let mut cache = LruCache::new(2); 44 | cache.insert(1, 10); 45 | cache.insert(2, 20); 46 | assert_eq!(cache.len(), 2); 47 | let opt1 = cache.remove(&1); 48 | assert!(opt1.is_some()); 49 | assert_eq!(opt1.unwrap(), 10); 50 | assert!(cache.get_mut(&1).is_none()); 51 | assert_eq!(cache.len(), 1); 52 | } 53 | 54 | #[test] 55 | fn test_change_capacity() { 56 | let mut cache = LruCache::new(2); 57 | assert_eq!(cache.capacity(), 2); 58 | cache.insert(1, 10); 59 | cache.insert(2, 20); 60 | cache.set_capacity(1); 61 | assert!(cache.get_mut(&1).is_none()); 62 | assert_eq!(cache.capacity(), 1); 63 | } 64 | 65 | #[test] 66 | fn test_remove() { 67 | let mut cache = LruCache::new(3); 68 | cache.insert(1, 10); 69 | cache.insert(2, 20); 70 | cache.insert(3, 30); 71 | cache.insert(4, 40); 72 | cache.insert(5, 50); 73 | cache.remove(&3); 74 | cache.remove(&4); 75 | assert!(cache.get_mut(&3).is_none()); 76 | assert!(cache.get_mut(&4).is_none()); 77 | cache.insert(6, 60); 78 | cache.insert(7, 70); 79 | cache.insert(8, 80); 80 | assert!(cache.get_mut(&5).is_none()); 81 | assert_eq!(cache.get_mut(&6), Some(&mut 60)); 82 | assert_eq!(cache.get_mut(&7), Some(&mut 70)); 83 | assert_eq!(cache.get_mut(&8), Some(&mut 80)); 84 | } 85 | 86 | #[test] 87 | fn test_clear() { 88 | let mut cache = LruCache::new(2); 89 | cache.insert(1, 10); 90 | cache.insert(2, 20); 91 | cache.clear(); 92 | assert!(cache.get_mut(&1).is_none()); 93 | assert!(cache.get_mut(&2).is_none()); 94 | assert!(cache.is_empty()) 95 | } 96 | 97 | #[test] 98 | fn test_iter() { 99 | let mut cache = LruCache::new(3); 100 | cache.insert(1, 10); 101 | cache.insert(2, 20); 102 | cache.insert(3, 30); 103 | cache.insert(4, 40); 104 | cache.insert(5, 50); 105 | assert_eq!( 106 | cache.iter().collect::>(), 107 | [(&3, &30), (&4, &40), (&5, &50)] 108 | ); 109 | assert_eq!( 110 | cache.iter_mut().collect::>(), 111 | [(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)] 112 | ); 113 | assert_eq!( 114 | cache.iter().rev().collect::>(), 115 | [(&5, &50), (&4, &40), (&3, &30)] 116 | ); 117 | assert_eq!( 118 | cache.iter_mut().rev().collect::>(), 119 | [(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)] 120 | ); 121 | } 122 | 123 | #[test] 124 | fn test_peek() { 125 | let mut cache = LruCache::new_unbounded(); 126 | cache.insert(1, 10); 127 | cache.insert(2, 20); 128 | cache.insert(3, 30); 129 | cache.insert(4, 40); 130 | cache.insert(5, 50); 131 | cache.insert(6, 60); 132 | 133 | assert_eq!(cache.remove_lru(), Some((1, 10))); 134 | assert_eq!(cache.peek(&2), Some(&20)); 135 | assert_eq!(cache.remove_lru(), Some((2, 20))); 136 | assert_eq!(cache.peek_mut(&3), Some(&mut 30)); 137 | assert_eq!(cache.remove_lru(), Some((3, 30))); 138 | assert_eq!(cache.get(&4), Some(&40)); 139 | assert_eq!(cache.remove_lru(), Some((5, 50))); 140 | } 141 | 142 | #[test] 143 | fn test_entry() { 144 | let mut cache = LruCache::new(4); 145 | 146 | cache.insert(1, 10); 147 | cache.insert(2, 20); 148 | cache.insert(3, 30); 149 | cache.insert(4, 40); 150 | cache.insert(5, 50); 151 | cache.insert(6, 60); 152 | 153 | assert_eq!(cache.len(), 4); 154 | 155 | cache.entry(7).or_insert(70); 156 | cache.entry(8).or_insert(80); 157 | cache.entry(9).or_insert(90); 158 | 159 | assert!(cache.len() <= 5); 160 | 161 | cache.raw_entry_mut().from_key(&10).or_insert(10, 100); 162 | cache.raw_entry_mut().from_key(&11).or_insert(11, 110); 163 | cache.raw_entry_mut().from_key(&12).or_insert(12, 120); 164 | 165 | assert!(cache.len() <= 5); 166 | } 167 | -------------------------------------------------------------------------------- /tests/serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde_impl")] 2 | 3 | use std::hash::BuildHasherDefault; 4 | 5 | use hashlink::{LinkedHashMap, LinkedHashSet}; 6 | use rustc_hash::FxHasher; 7 | use serde_test::{assert_tokens, Token}; 8 | 9 | #[test] 10 | fn map_serde_tokens_empty() { 11 | let map = LinkedHashMap::::new(); 12 | 13 | assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); 14 | } 15 | 16 | #[test] 17 | fn map_serde_tokens() { 18 | let mut map = LinkedHashMap::new(); 19 | map.insert('a', 10); 20 | map.insert('b', 20); 21 | map.insert('c', 30); 22 | 23 | assert_tokens( 24 | &map, 25 | &[ 26 | Token::Map { len: Some(3) }, 27 | Token::Char('a'), 28 | Token::I32(10), 29 | Token::Char('b'), 30 | Token::I32(20), 31 | Token::Char('c'), 32 | Token::I32(30), 33 | Token::MapEnd, 34 | ], 35 | ); 36 | } 37 | 38 | #[test] 39 | fn map_serde_tokens_empty_generic() { 40 | let map = LinkedHashMap::>::default(); 41 | 42 | assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); 43 | } 44 | 45 | #[test] 46 | fn map_serde_tokens_generic() { 47 | let mut map = LinkedHashMap::>::default(); 48 | map.insert('a', 10); 49 | map.insert('b', 20); 50 | map.insert('c', 30); 51 | 52 | assert_tokens( 53 | &map, 54 | &[ 55 | Token::Map { len: Some(3) }, 56 | Token::Char('a'), 57 | Token::I32(10), 58 | Token::Char('b'), 59 | Token::I32(20), 60 | Token::Char('c'), 61 | Token::I32(30), 62 | Token::MapEnd, 63 | ], 64 | ); 65 | } 66 | 67 | #[test] 68 | fn set_serde_tokens_empty() { 69 | let set = LinkedHashSet::::new(); 70 | 71 | assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]); 72 | } 73 | 74 | #[test] 75 | fn set_serde_tokens() { 76 | let mut set = LinkedHashSet::new(); 77 | set.insert(10); 78 | set.insert(20); 79 | set.insert(30); 80 | 81 | assert_tokens( 82 | &set, 83 | &[ 84 | Token::Seq { len: Some(3) }, 85 | Token::I32(10), 86 | Token::I32(20), 87 | Token::I32(30), 88 | Token::SeqEnd, 89 | ], 90 | ); 91 | } 92 | 93 | #[test] 94 | fn set_serde_tokens_generic() { 95 | let mut set = LinkedHashSet::>::default(); 96 | set.insert('a'); 97 | set.insert('b'); 98 | set.insert('c'); 99 | 100 | assert_tokens( 101 | &set, 102 | &[ 103 | Token::Seq { len: Some(3) }, 104 | Token::Char('a'), 105 | Token::Char('b'), 106 | Token::Char('c'), 107 | Token::SeqEnd, 108 | ], 109 | ); 110 | } 111 | --------------------------------------------------------------------------------